631 lines
37 KiB
JSON
631 lines
37 KiB
JSON
{
|
||
"schemaVersion": "1.0.0",
|
||
"components": [
|
||
{
|
||
"id": "progress-bar",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": [
|
||
"ProgressBar",
|
||
"ProgressBarProps"
|
||
],
|
||
"domContract": [
|
||
"nodedc-progress-bar"
|
||
],
|
||
"summary": "Accessible determinate or indeterminate linear progress, including the central ResourceRow slot.",
|
||
"variants": [
|
||
"determinate",
|
||
"indeterminate"
|
||
],
|
||
"rules": [
|
||
"Consumer supplies measured progress; elapsed time must not invent completion.",
|
||
"ResourceRow progress replaces status and occupies space between copy and actions.",
|
||
"Reduced motion preserves a visible non-animated indicator."
|
||
]
|
||
},
|
||
{
|
||
"id": "resource-row",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": [
|
||
"ResourceRow",
|
||
"ResourceList"
|
||
],
|
||
"domContract": [
|
||
"nodedc-resource-row",
|
||
"nodedc-resource-list"
|
||
],
|
||
"summary": "Mission Core AI Inference compact rows extracted for shared resource lists.",
|
||
"behavior": [
|
||
"wrapping title",
|
||
"optional metadata and status",
|
||
"optional leading status between icon and copy, vertically centered",
|
||
"canonical action controls",
|
||
"responsive action placement"
|
||
],
|
||
"rules": [
|
||
"The consumer supplies identity and states; the row owns presentation only.",
|
||
"Use ordinary list items and canonical buttons; do not nest actions inside a clickable row."
|
||
]
|
||
},
|
||
{
|
||
"id": "glass-surface",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["GlassSurface", "GlassMaterialSurface", "MapGlassSurface"],
|
||
"domContract": ["nodedc-glass", "nodedc-glass-material", "nodedc-map-glass", "nodedc-material-rim"],
|
||
"summary": "Matte application surfaces, the Engine V4 modal material and the light translucent surface used over Cesium imagery.",
|
||
"anatomy": ["theme-provided surface", "modal tint", "map-only light translucency", "gradient rim", "backdrop blur/saturation/brightness", "content"],
|
||
"variants": ["default", "strong", "soft", "map"],
|
||
"radiusVariants": ["card", "panel", "modal", "pill"],
|
||
"rules": [
|
||
"Geometry is invariant across application themes.",
|
||
"Compact rails of canonical round actions use the pill radius; consumers do not recreate it with a local border radius.",
|
||
"A material rim is a glass highlight, not a hard product-colored border.",
|
||
"Nested surfaces must use a softer tone to avoid card-inside-card noise.",
|
||
"GlassyMaterialSurface is restricted to modal Windows and the draggable Inspector.",
|
||
"MapGlassSurface is restricted to overlays over Cesium/map imagery and must match the map Toolbar translucency."
|
||
]
|
||
},
|
||
{
|
||
"id": "button",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": [
|
||
"Button",
|
||
"IconButton"
|
||
],
|
||
"domContract": [
|
||
"nodedc-button",
|
||
"nodedc-icon-button"
|
||
],
|
||
"summary": "Text and icon actions with shared sizing, states and computed accent contrast.",
|
||
"variants": [
|
||
"primary",
|
||
"secondary",
|
||
"ghost",
|
||
"danger",
|
||
"accent"
|
||
],
|
||
"sizes": [
|
||
"default",
|
||
"compact",
|
||
"dense"
|
||
],
|
||
"shapes": [
|
||
"default",
|
||
"pill",
|
||
"rounded"
|
||
],
|
||
"rules": [
|
||
"Icon-only actions are circular by default.",
|
||
"Controlled toggle actions expose aria-pressed and use the canonical active surface without changing geometry.",
|
||
"Filled accent actions derive foreground contrast from the actual accent.",
|
||
"Destructive actions remain neutral until confirmation unless danger is the principal message.",
|
||
"loading displays one centered indicator inside the initiating action, disables repeat activation and preserves dimensions and accessible name. Never place its spinner beside or below the action group.",
|
||
"Primary tone=neutral is white when enabled and gray when disabled in every theme/accent; use it for accent-independent operator actions without local CSS overrides."
|
||
]
|
||
},
|
||
{
|
||
"id": "activity-indicator",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["ActivityIndicator", "ActivityIndicatorProps", "ActivityIndicatorSize"],
|
||
"domContract": ["nodedc-activity-indicator"],
|
||
"summary": "Theme-independent indeterminate progress indicator for inline operations and pending action controls.",
|
||
"variants": ["default", "compact"],
|
||
"behavior": ["decorative by default", "optional status semantics", "static reduced-motion presentation"],
|
||
"rules": [
|
||
"Use Button.loading or IconButton.loading for actions and LoadingRegion for content. Standalone ActivityIndicator is limited to an explicit inline status or resource-row slot.",
|
||
"The process owner exposes aria-busy and visible pending copy; provide label only when the indicator itself is the status announcement.",
|
||
"The component never owns operation state, timing or completion.",
|
||
"Reduced-motion preferences stop rotation without hiding the pending-state affordance."
|
||
]
|
||
},
|
||
{
|
||
"id": "loading-region",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["LoadingRegion", "LoadingRegionProps"],
|
||
"domContract": ["nodedc-loading-region", "nodedc-loading-region__status"],
|
||
"summary": "Centered pending feedback within the content region that owns the request, without unmounting content.",
|
||
"rules": [
|
||
"The consumer owns loading and its terminal result; no timer or implicit network operation exists in this component.",
|
||
"Keep content mounted and reserve its dimensions while pending. Center the indicator within this region in normal and expanded layouts.",
|
||
"A command belongs to its initiating Button.loading; do not duplicate that command in a region spinner.",
|
||
"Remove loading on first usable content, failure or timeout. A live media connection alone is not usable content.",
|
||
"Use only for blocking initial content or explicit recovery. Background refresh with usable content does not cover it."
|
||
]
|
||
},
|
||
{
|
||
"id": "field",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["FieldFrame", "TextField", "TextAreaField"],
|
||
"domContract": ["nodedc-field", "nodedc-field__control"],
|
||
"summary": "Textual form controls with consistent labels, hints, geometry and focus surface.",
|
||
"rules": [
|
||
"Labels and validation copy are part of the field contract.",
|
||
"Keyboard focus changes the surface and remains visible without a browser-blue outline.",
|
||
"Browser autofill retains the canonical field material, text and caret; keyboard focus remains visible."
|
||
]
|
||
},
|
||
{
|
||
"id": "checker",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["Checker"],
|
||
"domContract": ["nodedc-checker"],
|
||
"summary": "Binary setting control derived from the redesigned Engine environment settings.",
|
||
"rules": [
|
||
"The visual anchor is circular, not a square native checkbox.",
|
||
"The control exposes checkbox semantics through role and aria-checked.",
|
||
"Checker contains one short label only; helper copy is a separate sibling block before the control."
|
||
]
|
||
},
|
||
{
|
||
"id": "range-control",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["RangeControl"],
|
||
"domContract": ["nodedc-range"],
|
||
"summary": "Filled pill range control with horizontal exact editing or a slim vertical scale with endpoints on the scene-inward side and a fixed centered label/value.",
|
||
"behavior": ["native range drag", "native caret and selection replacement", "automatic fill/base contrast", "unbounded finite exact editing by default", "Enter/blur commit", "Escape cancel", "independent optional exact-value bounds", "step normalization"],
|
||
"rules": [
|
||
"The accent fill follows the active application theme.",
|
||
"Vertical scales place formatLimit(min/max) on the configured scene-inward side (right by default, left with limitSide=left) in theme text, without units by default; label and formatValue(value) stay together at the center of the pill.",
|
||
"The vertical shaft is 40 percent of control height (20 percent slimmer than the original half-width variant); center and endpoint typography are 90 percent of their sm/xs tokens.",
|
||
"Central vertical text uses two identical layers clipped to the rounded fill, including partially covered glyphs. Vertical scales never have a perimeter border, outline or shadow, including focus; focus-visible underlines both central text layers with their existing contrast.",
|
||
"The native range remains the accessible drag input while its chrome is visually replaced.",
|
||
"The fill travels beneath the visible value; the persistent transparent native editor above the value receives exact-edit clicks without remounting.",
|
||
"Exact editing stays inside the existing value area and never expands the control.",
|
||
"Slider min/max define drag travel only; finite typed values are independent and may exceed that geometry.",
|
||
"exactValueBounds adds explicit domain limits when a parameter must reject values beyond them.",
|
||
"The browser places the caret at the clicked character, preserves native drag or keyboard selection, and replaces the selected substring on typing without pointer-state interception.",
|
||
"Editor foreground and caret switch automatically between theme text and on-accent tokens according to the actual fill edge beneath the value area.",
|
||
"The editor has no separate background box and keeps focus across parent window rerenders and pointer leave.",
|
||
"Editor keyboard events do not bubble into enclosing Window shortcuts."
|
||
]
|
||
},
|
||
{
|
||
"id": "color-field",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["ColorField"],
|
||
"domContract": ["nodedc-color-field"],
|
||
"summary": "Engine/BIM-derived swatch and HEX field with a theme-neutral portal palette.",
|
||
"behavior": ["controlled HEX value", "saturation/value plane", "hue slider", "quick colors", "portal palette", "keyboard spectrum adjustment"],
|
||
"rules": [
|
||
"Do not expose a browser-native color dialog as the product runtime UI.",
|
||
"The palette owns choice geometry; the consumer owns color validation, persistence and domain reaction."
|
||
]
|
||
},
|
||
{
|
||
"id": "dropdown",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["Dropdown"],
|
||
"domPackage": "@nodedc/ui-dom",
|
||
"domExports": ["createFloatingLayer"],
|
||
"domContract": ["nodedc-dropdown-surface", "nodedc-dropdown-option"],
|
||
"summary": "Shared portal/fixed floating layer for action and selection menus.",
|
||
"behavior": ["portal to document body", "viewport clamp", "vertical flip", "outside pointer close", "Escape close with trigger focus restore", "scroll and resize reposition", "contained menu scroll without geometry growth", "offscreen trigger close", "one open dropdown per window", "optional open-state notification"],
|
||
"rules": [
|
||
"Never render a runtime dropdown as an absolute child of a card, sticky header or scroll container.",
|
||
"Action menus and selection menus share floating behavior even when their row content differs.",
|
||
"The portal surface uses border-box sizing and contained overscroll so repeated menu scrolling cannot grow its measured width or move the underlying application surface."
|
||
]
|
||
},
|
||
{
|
||
"id": "select",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["Select"],
|
||
"domPackage": "@nodedc/ui-dom",
|
||
"domExports": ["createSelectController"],
|
||
"summary": "Theme-independent selection control using the canonical dropdown layer.",
|
||
"variants": ["integrated", "split", "inline"],
|
||
"behavior": ["controlled value", "optional search", "disabled options", "selected state", "portal menu", "optional independent row action"],
|
||
"rules": [
|
||
"An option.action is a sibling canonical IconButton with an independent disabled state; it closes the menu without selecting the option. Action-bearing menus use dialog semantics instead of nesting interactive controls in listbox options. Confirmation and mutation remain consumer-owned.",
|
||
"Select row actions match the compact Mission Core session-catalog reference: transparent 2.35rem hit column, 15px glyph, muted foreground and no round backing. An optional danger tone changes only hover/focus foreground; canonical keyboard focus remains visible.",
|
||
"Integrated is the single-pill Hub/Launcher form.",
|
||
"Split is the Engine form: a separate value surface and a 46 px toggle separated by an 8 px gap.",
|
||
"Inline is a compact label-only toolbar trigger without a persistent surface or chevron; its menu and keyboard behavior remain canonical.",
|
||
"Integrated Select is forbidden inside Inspector; use InspectorSelectField so the visible label is above a full-width split control.",
|
||
"The portal menu preserves its source-family row geometry instead of inheriting card radii."
|
||
]
|
||
},
|
||
{
|
||
"id": "window",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["Window", "WindowFooterActions"],
|
||
"domPackage": "@nodedc/ui-dom",
|
||
"domExports": ["createModalController"],
|
||
"domContract": ["nodedc-overlay", "nodedc-window"],
|
||
"summary": "Canonical controlled window for modal and right-side panel presentations.",
|
||
"behavior": ["portal to body", "focus entry", "modal-only focus trap", "focus restore", "Escape close", "backdrop close policy", "modal-only body scroll lock", "optional bounded dragging for modeless inspectors"],
|
||
"rules": [
|
||
"Open state belongs to the application; focus/layer behavior belongs to the component.",
|
||
"The same window contract is used by Launcher, CMS and SEO; theme variables supply color differences.",
|
||
"A right-side inspector is modeless by default: no dimming, no backdrop blur, no backdrop close, no focus trap and no body scroll lock.",
|
||
"A draggable inspector moves by its header and remains clamped to the viewport.",
|
||
"Closing a modeless inspector is never gated by autosave; preserve the draft, close immediately and report persistence failure through ToastStack.",
|
||
"Operational copy inside Window uses component typography tokens; browser-default paragraph or heading sizes are forbidden."
|
||
]
|
||
},
|
||
{
|
||
"id": "workspace-window",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["WorkspaceWindow", "WorkspaceWindowRect", "WorkspaceWindowProps"],
|
||
"domContract": ["nodedc-workspace-window"],
|
||
"summary": "Controlled modeless window for media, tools and synchronized views constrained to an application-owned workspace.",
|
||
"anatomy": ["controlled local rectangle", "title and optional status", "maximize and close actions", "scrollable body", "optional footer", "keyboard-accessible resize handle"],
|
||
"behavior": ["inline render without portal", "parent-bound dragging", "bottom-right resizing", "maximize within parent", "ResizeObserver reclamp", "pointer and keyboard geometry control", "application-owned activation and stacking"],
|
||
"rules": [
|
||
"The bounds element is an application-owned positioned and clipped workspace; WorkspaceWindow never escapes it or renders into document.body.",
|
||
"Rectangle, maximized state, visibility, activation and z-order are controlled by the application.",
|
||
"Use WorkspaceWindow for auxiliary views inside a stage; modal workflows and viewport inspectors continue to use Window.",
|
||
"Dragging and resizing remain clamped when the workspace changes size, including when it becomes smaller than the requested minimum."
|
||
]
|
||
},
|
||
{
|
||
"id": "confirmation-modal",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["ConfirmationModal"],
|
||
"summary": "Async-safe confirmation window for destructive and consequential operations.",
|
||
"behavior": ["pending state", "double-submit protection", "disabled close policy while pending"]
|
||
},
|
||
{
|
||
"id": "split-pane",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["SplitPane", "SplitPaneProps", "SplitPaneOrientation"],
|
||
"domContract": ["nodedc-split-pane", "nodedc-split-pane__panel", "nodedc-split-pane__separator"],
|
||
"summary": "Controlled two-panel layout with a pointer- and keyboard-resizable accessible separator.",
|
||
"anatomy": ["primary panel", "structural separator", "secondary panel"],
|
||
"variants": ["vertical", "horizontal"],
|
||
"behavior": ["controlled percentage", "optional resizable separator", "pointer capture drag", "Arrow/Home/End keyboard sizing", "ARIA separator range", "ratio preservation across host resize"],
|
||
"rules": [
|
||
"The application owns the controlled primary percentage and panel content; the component owns separator interaction and accessibility.",
|
||
"Minimum primary and secondary percentages clamp both pointer and keyboard changes.",
|
||
"The separator is a necessary structural divider, never a decorative perimeter border.",
|
||
"Viewport-local toolbars belong to their SplitPane panel, and embedded renderers receive the same controlled percentage instead of exposing cursor or pointer-position heuristics."
|
||
]
|
||
},
|
||
{
|
||
"id": "share-access-modal",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["ShareAccessModal"],
|
||
"domContract": ["nodedc-share-access-window", "nodedc-share-access", "nodedc-share-access__summary", "nodedc-share-access__member-list"],
|
||
"summary": "Engine-derived workflow access modal with compact member stack, role management and invite adapter slots.",
|
||
"behavior": ["controlled members", "compact expandable member stack", "role change", "member removal", "invite state", "immutable owner", "backdrop close disabled"],
|
||
"rules": [
|
||
"The component owns access-modal geometry and interaction; the consumer owns ACL requests and directory lookup.",
|
||
"Owner immutability and permission checks are supplied as member and canManage data.",
|
||
"The 600 px Engine composition uses 46 px invite controls and collapses to one column on mobile."
|
||
]
|
||
},
|
||
{
|
||
"id": "share-link-modal",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["ShareLinkModal"],
|
||
"domPackage": "@nodedc/ui-dom",
|
||
"domExports": ["createShareLinkController", "createModalController"],
|
||
"domContract": ["nodedc-window", "nodedc-field", "nodedc-button"],
|
||
"summary": "BIM-derived read-only resource link modal with copy progress and framework-neutral copy controller.",
|
||
"behavior": ["read-only link", "copy adapter", "copied state", "disabled empty state", "copy error adapter"],
|
||
"rules": [
|
||
"The resource service creates the URL; the modal only presents and copies it.",
|
||
"BIM DOM consumers combine the share-link controller with the canonical modal controller and core classes."
|
||
]
|
||
},
|
||
{
|
||
"id": "segmented-control",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["SegmentedControl"],
|
||
"domContract": ["nodedc-segmented"],
|
||
"summary": "Pill navigation used in the shared top header and compact mode switches.",
|
||
"sizes": ["default", "dense"],
|
||
"rules": [
|
||
"Dense is reserved for high-density in-viewer layer and mode toolbars; application headers retain default geometry."
|
||
]
|
||
},
|
||
{
|
||
"id": "app-header",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["AppHeader", "HeaderNavigation", "HeaderProfile", "HeaderProfileButton", "HeaderWorkspace", "HeaderAvatar"],
|
||
"domContract": ["nodedc-header-shell", "nodedc-header", "nodedc-header__row"],
|
||
"summary": "Strict Launcher-preset NODE.DC header with a 68 px outer toolbar, 48 px visible row and fixed three-axis geometry.",
|
||
"anatomy": ["left brand", "optional left context", "center navigation/workspace", "right actions/profile"],
|
||
"rules": [
|
||
"The logo occupies the same visual position and geometry across applications.",
|
||
"Light single-color assets may opt into brandMonochrome / monochrome for theme contrast; full-color images are unchanged by default.",
|
||
"Product routes and profile content are application data passed into stable slots.",
|
||
"The canonical application header is fixed and preserves the Launcher three-axis logo / navigation / profile positions.",
|
||
"Consumers supply data and actions but cannot override preset geometry through local className or style props."
|
||
]
|
||
},
|
||
{
|
||
"id": "user-profile-menu",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["UserProfileMenu", "UserProfileMenuAction"],
|
||
"domContract": ["nodedc-user-profile-menu", "nodedc-user-profile-card", "nodedc-user-profile-card__action"],
|
||
"summary": "Canonical user profile dropdown for NODE.DC application headers with identity cover and application-owned actions.",
|
||
"behavior": ["portal dropdown", "profile identity card", "theme-independent cover", "action links and callbacks", "outside pointer and Escape close"],
|
||
"rules": [
|
||
"The component owns menu geometry and profile presentation; the application owns settings, profile and logout actions.",
|
||
"Use the existing Dropdown engine so the menu is never clipped by the fixed application header.",
|
||
"Do not embed product permissions or sharing rules in the visual menu."
|
||
]
|
||
},
|
||
{
|
||
"id": "feature-settings-window",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["FeatureSettingsWindow", "FeatureSettingsSection"],
|
||
"domContract": ["nodedc-feature-settings-window", "nodedc-feature-settings__navigation", "nodedc-feature-settings__content"],
|
||
"summary": "Engine-derived large settings window with module identity, grouped feature navigation and application-owned content.",
|
||
"behavior": ["canonical modal focus behavior", "controlled active section", "grouped navigation", "responsive single-column layout"],
|
||
"rules": [
|
||
"The window owns settings-shell geometry only; forms, API calls and authorization remain application-owned.",
|
||
"FeatureSettingsWindow composes the canonical Window and must not create a second portal or focus trap.",
|
||
"Module colors are supplied through the active NODE.DC Design Profile rather than hard-coded product CSS."
|
||
]
|
||
},
|
||
{
|
||
"id": "application-shell",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["ApplicationShell", "ApplicationPanel", "useApplicationWorkspace"],
|
||
"domPackage": "@nodedc/ui-dom",
|
||
"domExports": ["createApplicationWorkspaceController"],
|
||
"domContract": ["nodedc-app-shell", "nodedc-application-panel"],
|
||
"summary": "Launcher-derived application template with fixed header, media stage, left navigation and a separate expandable content window.",
|
||
"anatomy": ["fixed AppHeader", "stage", "left navigation", "right content window", "persistent utility actions", "expand and close actions"],
|
||
"behavior": ["one shared navigation/content state machine", "navigation shifts stage", "content opens beside navigation", "expanded content replaces stage", "global utility actions remain in the panel header across sections", "mobile panels use the available viewport sequentially", "independent content scrolling"],
|
||
"rules": [
|
||
"The bottom Launcher service rail is product-specific and is not part of the general application template.",
|
||
"Desktop page gap is 20 px and navigation width follows the Launcher 332–352 px range.",
|
||
"Applications supply routes, profile data, stage media and panel content without changing shell geometry.",
|
||
"Light panels use the SEO white surface and shadow tokens rather than a dark shell with inverted text.",
|
||
"A layout-level save action belongs to ApplicationPanel.utilityActions and is never duplicated inside individual content cards."
|
||
]
|
||
},
|
||
{
|
||
"id": "toolbar",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["Toolbar"],
|
||
"domPackage": "@nodedc/ui-dom",
|
||
"domExports": ["createToolbarController"],
|
||
"domContract": ["nodedc-toolbar-wrap", "nodedc-toolbar", "nodedc-toolbar__button"],
|
||
"summary": "Engine/BIM-derived magnifying application toolbar with left, right and bottom placements.",
|
||
"variants": ["left", "right", "bottom"],
|
||
"behavior": ["controlled active item", "spring lens magnification without flex reflow", "axis-aware neighbor shift", "optional delayed autohide hotzone", "theme-independent geometry"],
|
||
"rules": [
|
||
"Engine defaults are background #111115, border #111117, outline #1c1c1c, min 25 px, max 87 px and five lens items.",
|
||
"Toolbar actions call application navigation; they do not duplicate route state.",
|
||
"Placement and material are controlled values and belong to the persisted application layout.",
|
||
"The shared component owns pointer tracking, spring animation, lens geometry and autohide timers; applications must not reimplement them."
|
||
]
|
||
},
|
||
{
|
||
"id": "icon",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["Icon"],
|
||
"domContract": ["svg using currentColor"],
|
||
"summary": "Audited semantic icon subset shared by NODE.DC applications instead of product-local vendor imports.",
|
||
"variants": ["14 px", "16 px", "18 px"],
|
||
"rules": [
|
||
"Use semantic names from registry/icons.json.",
|
||
"Use layers for visibility controls of map or visual source layers; settings remains general configuration.",
|
||
"The containing component owns surface, hit target and state; the icon owns only the glyph and uses the canonical 16 px default without an extra CSS scale.",
|
||
"Do not copy complete Lucide or Font Awesome catalogs into an application."
|
||
]
|
||
},
|
||
{
|
||
"id": "admin-navigation-panel",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["AdminNavigationPanel"],
|
||
"domContract": ["nodedc-admin-panel"],
|
||
"summary": "Hub-derived left administration panel with context selectors, route navigation, close action and footer identity.",
|
||
"anatomy": ["eyebrow and title", "close action", "workspace context", "company context", "route items", "footer identity"],
|
||
"rules": [
|
||
"The panel shell, full-bleed pills and icon circles are library geometry; routes and identity data remain application-owned.",
|
||
"The desktop panel follows the Launcher 332–352 px width range with a 21.6 px shell radius and a 20 px page gap.",
|
||
"Active route state uses the active surface and icon contrast from the theme."
|
||
]
|
||
},
|
||
{
|
||
"id": "application-side-panel",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["ApplicationSidePanel", "ApplicationSidePanelProps"],
|
||
"domContract": ["nodedc-application-side-panel", "nodedc-app-shell__end-panel"],
|
||
"summary": "Theme-aware trailing application panel paired with AdminNavigationPanel and hosted in a separate ApplicationShell end column.",
|
||
"anatomy": ["eyebrow and title", "optional description", "close action", "scrollable body", "optional footer"],
|
||
"behavior": ["right-to-left entrance", "separate push column", "controlled visibility", "theme token inheritance"],
|
||
"rules": [
|
||
"The panel uses the same 332–352 px geometry, radius, surface, shadow and circular actions as AdminNavigationPanel.",
|
||
"ApplicationShell shrinks the expanded content/stage by one panel width plus the canonical page gap; the side panel never overlays the desktop work area.",
|
||
"The owning ApplicationPanel header action controls visibility; close always remains available and workspace interaction does not dismiss the panel implicitly.",
|
||
"Use this panel for application-level settings/detail. Bounded scene tools and subject cards remain WorkspaceWindow instances."
|
||
]
|
||
},
|
||
{
|
||
"id": "media-source-field",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": [
|
||
"MediaSourceField"
|
||
],
|
||
"domPackage": "@nodedc/ui-dom",
|
||
"domExports": [
|
||
"createMediaSourceController"
|
||
],
|
||
"domContract": [
|
||
"nodedc-media-field",
|
||
"nodedc-media-control",
|
||
"nodedc-media-source-button",
|
||
"nodedc-media-preview"
|
||
],
|
||
"summary": "Launcher/CMS media control for video, image or logo file/URL sources, filename, preview and adapter-provided storage state.",
|
||
"behavior": [
|
||
"controlled file/url source",
|
||
"native accessible file input",
|
||
"URL input",
|
||
"image/video preview",
|
||
"path, hint and error slots",
|
||
"controlled disabled state locks file, URL and source switching during a parent save/upload"
|
||
],
|
||
"rules": [
|
||
"The component owns geometry, source switching and accessibility.",
|
||
"The consumer owns media library, storage upload, validation and the persisted URL.",
|
||
"Do not fork the field by asset type or backend; configure its accepted media and provide an adapter callback.",
|
||
"Application layout persistence may save stage video and header mark together, but remains outside the visual component."
|
||
]
|
||
},
|
||
{
|
||
"id": "settings-card",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["SettingsCard", "Switch"],
|
||
"domContract": ["nodedc-settings-card", "nodedc-switch"],
|
||
"summary": "Neutral administration group with title metadata, actions, content and a compact binary switch.",
|
||
"rules": [
|
||
"The card owns grouping geometry but not product form schemas.",
|
||
"Use align=center for compact result or empty messages: center the content on both axes and omit an empty body. The default start layout remains unchanged.",
|
||
"Section and empty-state titles use the compact md token; descriptions use sm. Page/window title sizes and browser heading defaults are forbidden inside cards.",
|
||
"Use Switch for compact visibility/enable states; use Checker for the Engine inspector treatment.",
|
||
"Switch keeps its track width beside wrapped labels. The checked thumb uses on-accent contrast; the unchecked track follows theme text instead of a fixed white tint."
|
||
]
|
||
},
|
||
{
|
||
"id": "status-badge",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["StatusBadge"],
|
||
"variants": ["badge", "indicator"],
|
||
"domContract": ["nodedc-status"],
|
||
"summary": "Semantic status pill whose tone is independent from the application accent.",
|
||
"behavior": ["optional pulse animates only the status lamp", "pulse is static with reduced motion"]
|
||
},
|
||
{
|
||
"id": "toast",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["ToastCard", "ToastStack", "ToastItem", "ToastTone"],
|
||
"domContract": ["nodedc-toast-viewport", "nodedc-toast", "nodedc-toast__icon", "nodedc-toast__copy"],
|
||
"summary": "Tasker-derived non-blocking status notification with a bottom-right glass stack.",
|
||
"variants": ["success", "error", "warning", "info", "loading"],
|
||
"behavior": ["controlled items", "independent 10 second default auto-dismiss per terminal item", "manual dismiss", "portal viewport", "polite live region"],
|
||
"rules": [
|
||
"Applications own operation state and message copy; ToastStack owns viewport geometry and dismissal timing.",
|
||
"Errors and status copy use the compact Toast typography; consumers do not substitute browser-default paragraphs or title-sized text.",
|
||
"Adding or updating another notification never restarts the lifetime of an existing item; each item owns its timer by stable id.",
|
||
"Loading notifications remain until the operation updates or dismisses them.",
|
||
"Status notifications never replace a blocking confirmation modal."
|
||
]
|
||
},
|
||
{
|
||
"id": "drag-drop",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["DragHandle", "DragDropRoot", "DraggableItem", "DropZone", "SortableScope", "SortableItem", "SortableList"],
|
||
"domContract": ["nodedc-drag-handle"],
|
||
"summary": "Engine-derived handle-only drag, transfer and sortable primitives with the canonical six-dot grip and a 6 px activation threshold.",
|
||
"behavior": ["handle-only drag", "cross-list transfer with explicit overlap acceptance", "vertical-axis reorder", "drop-zone state", "keyboard attributes from dnd-kit"],
|
||
"rules": [
|
||
"The six-dot handle is the only drag initiator; clicking the row keeps its normal navigation or selection action.",
|
||
"Sortable rows are visually constrained to the vertical axis and cannot pull their layout horizontally.",
|
||
"A transfer is accepted only when the dragged surface overlaps the destination by at least the consumer-defined threshold; Module Foundry uses 20 percent.",
|
||
"Consumers own domain mutations while the package owns sensors, transforms, accessible drag attributes and geometry.",
|
||
"Repeated page-template drops create distinct application page instances instead of consuming the source template.",
|
||
"A reordered application page array is the single source of truth for both composition and navigation order."
|
||
]
|
||
},
|
||
{
|
||
"id": "inspector",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": ["Inspector", "ControlRow", "InspectorSelectField"],
|
||
"domContract": ["nodedc-inspector", "nodedc-control-row"],
|
||
"summary": "Accordion settings/definition inspector derived only from the redesigned Engine environment and NDC agent inspector.",
|
||
"rules": [
|
||
"Legacy Engine inspectors are not reference implementations.",
|
||
"Domain-specific field definitions remain in Engine; reusable layout and controls live here.",
|
||
"Desktop Engine geometry is fixed at 390 px panel, 330 px content, 154/14/162 px control rows and 50 px section headers with a 12 px radius.",
|
||
"Inspector supports controlled openSections/onOpenSectionsChange state so a consumer can persist the exact accordion layout without remount defaults.",
|
||
"Inspector selection fields use InspectorSelectField only: a stacked visible label and the 276/8/46 px split control; integrated pills are prohibited.",
|
||
"The panel variant reuses AdminNavigationPanel pill, icon and theme tokens while retaining the same controlled accordion state and domain-owned content.",
|
||
"Accent-filled section headers belong to Environment Settings; neutral headers remain available for other approved inspector contexts."
|
||
]
|
||
},
|
||
{
|
||
"id": "environment-settings",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": [
|
||
"EnvironmentSettingsWindow",
|
||
"EnvironmentMediaPlaylistEditor"
|
||
],
|
||
"domContract": [
|
||
"nodedc-environment-settings",
|
||
"nodedc-environment-media-playlist"
|
||
],
|
||
"summary": "Shared avatar Settings → Environment composition for product/home copy, quick actions and image/video playlists.",
|
||
"behavior": [
|
||
"product-configured page list",
|
||
"draft/reset/save",
|
||
"upload adapter",
|
||
"ordered media playlist",
|
||
"image timing",
|
||
"parent save/upload disabled state"
|
||
],
|
||
"rules": [
|
||
"Reuse FeatureSettingsWindow and existing form primitives; never fork an application-specific settings form.",
|
||
"Consumers own page/action IDs, storage, revision conflicts, authentication and upload URLs.",
|
||
"A single-home application passes one surface; multi-section applications pass all admitted pages.",
|
||
"Closing the window preserves host authority and never sends device commands."
|
||
]
|
||
},
|
||
{
|
||
"id": "landing-stage",
|
||
"status": "baseline",
|
||
"package": "@nodedc/ui-react",
|
||
"exports": [
|
||
"LandingStage",
|
||
"EnvironmentBackgroundMedia"
|
||
],
|
||
"domContract": [
|
||
"nodedc-landing-stage",
|
||
"nodedc-landing-stage__media"
|
||
],
|
||
"summary": "Shared product landing stage with editable copy, quick actions and ordered image/video background.",
|
||
"behavior": [
|
||
"image timer",
|
||
"video end advance",
|
||
"skip failed media",
|
||
"flat empty background",
|
||
"product status/footer slots"
|
||
],
|
||
"rules": [
|
||
"No decorative radial gradient or invented graphic appears without configured media.",
|
||
"Applications supply content and actions, not duplicate stage markup.",
|
||
"Background playback and scene navigation never own device acquisition."
|
||
]
|
||
}
|
||
]
|
||
}
|