Przejdź do głównej zawartości

Author a workspace symbol

Ta treść nie jest jeszcze dostępna w Twoim języku.

A workspace symbol adds equipment that the built-in catalog lacks to every drawing in a workspace. This guide writes one in a pulled workspace. The definition fields and hooks are described in Workspace symbols.

  1. Check the built-in catalog first: builtinGraphicsSymbols lists the symbols of the installed package version, and graphics.symbols.search those of the server, with their properties and ports.
  2. Create a .tsx file under src/symbols/, one file per symbol.
  3. Default-export a defineGraphicsSymbol definition with a unique id, a name factory, the authored width and height, stretch, ports, a properties factory, and the Component. Do not start the ID with hmi., which is reserved for built-in symbols. Never reuse an ID for an unrelated object: placements of the old symbol render the new one.
  1. Declare a closed TypeBox object with a valid default for every property.
  2. Label each field and literal choice with title, using translated messages.
  3. Bound numeric inputs with minimum and maximum, but not a reading that is only displayed as text: bound values are clamped.
  4. Mark a color with graphicsColor: true, and text that viewers read with graphicsText: true.
  5. To receive unknown when a state input is unavailable, add an unknown literal to its union.
  6. For a reading with a unit, name the unit property with unitProperty.
  7. Return the name, action labels, and properties from factories, such as name: () => t("key"), so their text follows the active language.
  1. Return your own <svg> root with a viewBox, or HTML controls.
  2. Create clip, gradient, and mask IDs with useId, so placements do not collide.
  3. For a stretchable symbol (stretch: true), draw the artwork from the viewport size of useGraphicsSymbolViewport(), so each drawn connection stays at its port. Anchor ports with anchorX or anchorY where they keep a distance from an edge.
  4. Lay out resizable controls from the viewport’s width and height, so labels are not distorted.
  5. Use GraphicsSymbolText instead of <text>, GraphicsSymbolCaption for a label along the bottom edge, GraphicsSymbolCaptionBlock for the tag and status lines, and GraphicsSymbolUpright for a display face, so text stays upright when the placement turns or mirrors.
  1. Read each property’s state with useGraphicsSymbolProperty(name).
  2. Leave out an optional reading that is not assigned, instead of showing its default as a value.
  3. Render an unknown property as unknown: ”—” for a reading, with formatGraphicsSymbolReading, and an explicit unknown indication for a state.
  4. Pause motion that the component manages while editing is true, or while a property that drives it is not fresh. Respect the browser’s reduced-motion preference.
  1. Declare control names in actions, such as actions: () => ({ activate: "Pump command" }).
  2. In the component, connect a Button to useGraphicsSymbolAction("activate"). Do not add a second handler that writes to equipment.
  3. When neighbors can sit against the symbol, such as rooms sharing a wall, declare its body, so whole-object clicks land only on the equipment itself.
  1. Add a catalog factory with category, industries, description, keywords, and examples. Add family, variants, essential, units, and grid where they apply.
  2. Give each port a role and a direction.
  3. Check the result with serializeGraphicsSymbolCatalog(definitions, locale).
  1. Run pnpm build and fix any errors.
  2. Push the workspace. Every dashboard picks up the symbol on reload.
  3. Do not rename or remove a property or port that placements use. If you must, find the placements that show an incompatibility and repair them.