@jini-ai/ui 0.4.4 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +20 -0
  3. package/dist/core/theme/default.d.ts +4 -0
  4. package/dist/core/theme/default.js +11 -0
  5. package/dist/core/theme/stylesheet.d.ts +8 -0
  6. package/dist/core/theme/stylesheet.js +14 -0
  7. package/dist/core/theme/types.d.ts +39 -0
  8. package/dist/core/theme/types.js +2 -0
  9. package/dist/core/theme/validation.d.ts +15 -0
  10. package/dist/core/theme/validation.js +55 -0
  11. package/dist/features/admin-widgets/components/Select/Select.d.ts +11 -3
  12. package/dist/features/admin-widgets/components/Select/Select.hooks.d.ts +8 -13
  13. package/dist/features/admin-widgets/components/Select/Select.hooks.js +37 -215
  14. package/dist/features/admin-widgets/components/Select/Select.js +4 -3
  15. package/dist/features/appearance/constants.js +1 -1
  16. package/dist/features/connectors/rules.d.ts +1 -6
  17. package/dist/features/connectors/types.d.ts +1 -6
  18. package/dist/features/connectors/types.js +1 -6
  19. package/dist/features/execution/http-adapter.d.ts +111 -0
  20. package/dist/features/execution/http-adapter.js +160 -0
  21. package/dist/features/execution/index.d.ts +4 -0
  22. package/dist/features/execution/index.js +2 -0
  23. package/dist/features/execution/react/hooks/use-execution-credential.hooks.d.ts +232 -0
  24. package/dist/features/execution/react/hooks/use-execution-credential.hooks.js +217 -0
  25. package/dist/features/html-editor/canvas-style.d.ts +1 -1
  26. package/dist/features/html-editor/canvas-style.js +2 -2
  27. package/dist/features/i18n/dictionaries/settings-dialog.ar.js +2 -0
  28. package/dist/features/i18n/dictionaries/settings-dialog.bn.js +2 -0
  29. package/dist/features/i18n/dictionaries/settings-dialog.de.js +2 -0
  30. package/dist/features/i18n/dictionaries/settings-dialog.en.js +2 -0
  31. package/dist/features/i18n/dictionaries/settings-dialog.es.js +2 -0
  32. package/dist/features/i18n/dictionaries/settings-dialog.fa.js +2 -0
  33. package/dist/features/i18n/dictionaries/settings-dialog.fr.js +2 -0
  34. package/dist/features/i18n/dictionaries/settings-dialog.hi.js +2 -0
  35. package/dist/features/i18n/dictionaries/settings-dialog.hu.js +2 -0
  36. package/dist/features/i18n/dictionaries/settings-dialog.id.js +2 -0
  37. package/dist/features/i18n/dictionaries/settings-dialog.it.js +2 -0
  38. package/dist/features/i18n/dictionaries/settings-dialog.ja.js +2 -0
  39. package/dist/features/i18n/dictionaries/settings-dialog.ko.js +2 -0
  40. package/dist/features/i18n/dictionaries/settings-dialog.pl.js +2 -0
  41. package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +2 -0
  42. package/dist/features/i18n/dictionaries/settings-dialog.ru.js +2 -0
  43. package/dist/features/i18n/dictionaries/settings-dialog.th.js +2 -0
  44. package/dist/features/i18n/dictionaries/settings-dialog.tr.js +2 -0
  45. package/dist/features/i18n/dictionaries/settings-dialog.uk.js +2 -0
  46. package/dist/features/i18n/dictionaries/settings-dialog.ur.js +2 -0
  47. package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +2 -0
  48. package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +2 -0
  49. package/dist/features/i18n/dictionary-translator.d.ts +5 -2
  50. package/dist/features/i18n/dictionary-translator.js +1 -1
  51. package/dist/features/i18n/index.d.ts +1 -1
  52. package/dist/features/i18n/index.js +1 -1
  53. package/dist/features/i18n/template-i18n.d.ts +11 -0
  54. package/dist/features/i18n/template-i18n.js +12 -0
  55. package/dist/features/interactive-ui/providers/recharts/chart-tokens.d.ts +1 -1
  56. package/dist/features/interactive-ui/providers/recharts/chart-tokens.js +1 -1
  57. package/dist/features/lexical-rich-text-editor/deserialize.d.ts +0 -5
  58. package/dist/features/lexical-rich-text-editor/deserialize.js +0 -5
  59. package/dist/features/lexical-rich-text-editor/mention-node.d.ts +5 -17
  60. package/dist/features/lexical-rich-text-editor/mention-node.js +5 -17
  61. package/dist/features/lexical-rich-text-editor/mention-parser.d.ts +2 -4
  62. package/dist/features/lexical-rich-text-editor/serialize.d.ts +0 -4
  63. package/dist/features/lexical-rich-text-editor/serialize.js +0 -4
  64. package/dist/features/lexical-rich-text-editor/types.d.ts +3 -13
  65. package/dist/features/lexical-rich-text-editor/types.js +3 -13
  66. package/dist/features/mcp-ui/early-message-buffer.d.ts +1 -2
  67. package/dist/features/mcp-ui/early-message-buffer.js +1 -2
  68. package/dist/features/mcp-ui/escape.d.ts +4 -0
  69. package/dist/features/mcp-ui/escape.js +2 -9
  70. package/dist/features/mcp-ui/index.d.ts +1 -0
  71. package/dist/features/mcp-ui/index.js +1 -0
  72. package/dist/features/mcp-ui/protocol.d.ts +2 -5
  73. package/dist/features/mcp-ui/protocol.js +2 -5
  74. package/dist/features/mcp-ui/resource.d.ts +47 -7
  75. package/dist/features/mcp-ui/resource.js +5 -8
  76. package/dist/features/mcp-ui/secret-card.d.ts +115 -0
  77. package/dist/features/mcp-ui/secret-card.js +137 -0
  78. package/dist/features/mcp-ui/surfaces/confirmation.js +5 -0
  79. package/dist/features/mcp-ui/surfaces/fields.d.ts +5 -2
  80. package/dist/features/mcp-ui/surfaces/fields.js +3 -1
  81. package/dist/features/mcp-ui/surfaces/form.d.ts +4 -1
  82. package/dist/features/mcp-ui/surfaces/form.js +65 -3
  83. package/dist/features/mcp-ui/surfaces/outcome.d.ts +2 -0
  84. package/dist/features/mcp-ui/surfaces/text-input.d.ts +14 -6
  85. package/dist/features/mcp-ui/surfaces/text-input.js +16 -2
  86. package/dist/features/mcp-ui/surfaces/tokens.js +1 -1
  87. package/dist/features/memory/react/components/MemoryConnectedPanel.d.ts +1 -1
  88. package/dist/features/memory/react/components/MemoryConnectedPanel.js +0 -1
  89. package/dist/features/panel-kit/helpers/format-timestamp.d.ts +5 -3
  90. package/dist/features/panel-kit/helpers/format-timestamp.js +13 -4
  91. package/dist/features/panel-kit/helpers/permissions.js +2 -0
  92. package/dist/features/panel-kit/helpers/resolve-active-tab-id.js +2 -0
  93. package/dist/features/panel-kit/helpers/standing-draft-local-backup.d.ts +51 -0
  94. package/dist/features/panel-kit/helpers/standing-draft-local-backup.js +77 -0
  95. package/dist/features/panel-kit/helpers/standing-draft-recovery-message.d.ts +8 -0
  96. package/dist/features/panel-kit/helpers/standing-draft-recovery-message.js +10 -0
  97. package/dist/features/panel-kit/hooks/use-async-action.hooks.d.ts +1 -0
  98. package/dist/features/panel-kit/hooks/use-dirty-guard.hooks.d.ts +1 -0
  99. package/dist/features/panel-kit/hooks/use-dirty-guard.hooks.js +1 -0
  100. package/dist/features/panel-kit/hooks/use-serial-writes.hooks.d.ts +8 -0
  101. package/dist/features/panel-kit/hooks/use-serial-writes.hooks.js +3 -0
  102. package/dist/features/panel-kit/hooks/use-settings-slice.hooks.d.ts +211 -0
  103. package/dist/features/panel-kit/hooks/use-settings-slice.hooks.js +382 -0
  104. package/dist/features/panel-kit/hooks/use-standing-draft-autosave.hooks.d.ts +179 -0
  105. package/dist/features/panel-kit/hooks/use-standing-draft-autosave.hooks.js +300 -0
  106. package/dist/features/panel-kit/index.d.ts +7 -1
  107. package/dist/features/panel-kit/index.js +5 -1
  108. package/dist/features/resource-dashboard/types.d.ts +8 -41
  109. package/dist/features/resource-dashboard/types.js +3 -26
  110. package/dist/features/tab-strip/constants.d.ts +3 -4
  111. package/dist/features/tab-strip/constants.js +3 -4
  112. package/dist/features/tab-strip/dependencies.d.ts +1 -6
  113. package/dist/features/tab-strip/dependencies.js +1 -6
  114. package/dist/features/tab-strip/react/components/TabBar.d.ts +33 -1
  115. package/dist/features/tab-strip/react/components/TabBar.hooks.d.ts +57 -5
  116. package/dist/features/tab-strip/react/components/TabBar.hooks.js +63 -5
  117. package/dist/features/tab-strip/react/components/TabBar.js +12 -1
  118. package/dist/features/tab-strip/rules.d.ts +4 -17
  119. package/dist/features/tab-strip/rules.js +4 -17
  120. package/dist/features/tab-strip/types.d.ts +2 -13
  121. package/dist/icon-name.d.ts +1 -1
  122. package/dist/icon-name.js +1 -0
  123. package/dist/index.d.ts +42 -417
  124. package/dist/index.js +42 -430
  125. package/dist/react/components/CustomSelect.d.ts +6 -2
  126. package/dist/react/components/CustomSelect.js +20 -91
  127. package/dist/react/components/Icon.d.ts +6 -0
  128. package/dist/react/components/Icon.js +12 -0
  129. package/dist/react/components/select-popover.d.ts +106 -0
  130. package/dist/react/components/select-popover.js +210 -0
  131. package/dist/renderers/sandbox-scripts.d.ts +29 -0
  132. package/dist/renderers/sandbox-scripts.js +127 -0
  133. package/dist/renderers/sandboxed-document.js +3 -86
  134. package/dist/renderers/srcdoc/build.d.ts +10 -17
  135. package/dist/renderers/srcdoc/build.js +31 -234
  136. package/dist/styles/variables.css +2 -2
  137. package/dist/theme/apply.d.ts +1 -1
  138. package/dist/theme/apply.js +2 -2
  139. package/dist/theme/color-scheme.d.ts +1 -1
  140. package/dist/theme/default.d.ts +1 -3
  141. package/dist/theme/default.js +2 -10
  142. package/dist/theme/index.d.ts +3 -3
  143. package/dist/theme/index.js +2 -2
  144. package/dist/theme/stylesheet.d.ts +1 -7
  145. package/dist/theme/stylesheet.js +2 -13
  146. package/dist/theme/types.d.ts +1 -38
  147. package/dist/theme/types.js +2 -1
  148. package/dist/theme/validation.d.ts +1 -14
  149. package/dist/theme/validation.js +2 -54
  150. package/dist/utils/endpoint-policy.d.ts +21 -39
  151. package/dist/utils/endpoint-policy.js +19 -107
  152. package/dist/utils/file-system-errors.d.ts +1 -2
  153. package/dist/utils/file-system-errors.js +1 -2
  154. package/dist/utils/ime-composing.d.ts +0 -3
  155. package/dist/utils/ime-composing.js +0 -3
  156. package/dist/utils/platform.d.ts +1 -4
  157. package/dist/utils/platform.js +1 -4
  158. package/dist/utils/smooth-scroll-to-top.d.ts +1 -3
  159. package/dist/utils/smooth-scroll-to-top.js +3 -13
  160. package/dist/utils/timezone.js +1 -5
  161. package/dist/utils/uuid.d.ts +0 -3
  162. package/dist/utils/uuid.js +0 -3
  163. package/dist/utils/visual-stability.d.ts +1 -3
  164. package/dist/utils/visual-stability.js +1 -3
  165. package/package.json +74 -15
package/dist/index.d.ts CHANGED
@@ -1,420 +1,45 @@
1
1
  /**
2
- * Archived provenance rationale:
3
- * ### Design decisions worth flagging
4
- *
5
- * - **`title`/`detail` are host-supplied, not computed from a status+kind
6
- * lookup table.** Both source cards hardcode branded, kind-specific copy
7
- * ("Open Design is rebuilding tokens", "Workspace update ready" — see the
8
- * purity-grep note below for why that exact text can't even appear in this
9
- * package's comments). Baking any "kind"-aware copy-selection logic into the
10
- * generic component would just re-embed OD's product vocabulary (job
11
- * "kind" — generation/revision/token-contract-rebuild — is OD-specific)
12
- * under a different name. The generic component instead takes optional
13
- * `title`/`detail` and falls back to a neutral, status-only default
14
- * (`Queued`/`Running`/`Complete`/`Needs attention`) when omitted. Computing
15
- * richer, kind-aware copy is left to the host.
16
- * - **`progress: number | 'indeterminate'`** — neither source occurrence ever
17
- * actually produces an indeterminate state (both always compute a 0-100
18
- * percentage). It's included anyway because the task's own required test
19
- * matrix asked for indeterminate-vs-determinate coverage, and because it's
20
- * a natural, forward-looking capability for Jini's own Run/Agent/Tool
21
- * dashboards (an agent step with no known total duration) — this is a
22
- * deliberate generalization beyond what the two source cards themselves
23
- * needed, called out here rather than silently added.
24
- * - **Per-item `label` values are not run through `useT()`.** `steps[]`/
25
- * `secondaryItems[]` mix genuinely dynamic content (a todo's own text, an
26
- * agent-touched file path) with the reference adapter's static fallback
27
- * step titles, indistinguishably once they're both just strings in the same
28
- * array — there's no way for the component to tell them apart. This matches
29
- * the precedent already set by `ConnectorCard` not wrapping `connector.name`/
30
- * `connector.category`. What *is* wrapped in `t()`, and covered by a real
31
- * `I18nProvider` test: the fallback title/detail, the progress-bar
32
- * `aria-label`, and the default "Files touched" secondary-items heading.
33
- * - **Adapters take a `*Like` structural input, not real `@open-design/contracts`
34
- * types.** The task's own framing allowed shipping these as "documented
35
- * reference adapters" for OD-shaped input; going one step further, the
36
- * input types are locally declared minimal structural subsets rather than
37
- * actual imports of an external, unvendored package — this package has zero
38
- * dependency on `@open-design/contracts`, and a host whose real types are a
39
- * structural superset can pass them in directly (TypeScript structural
40
- * typing).
41
- * - **Slicing (`maxSteps`/`maxSecondaryItems`) moved from the adapter to the
42
- * component.** The source cards slice at render time (`todos.slice(0, 6)`,
43
- * `fileOps.slice(0, 5)`) inside the component itself. The adapters here
44
- * return the *full* derived list; `ProgressCard` truncates for display via
45
- * props (defaulting to the same 6/5 caps). This keeps the adapter's output
46
- * data-complete and makes the truncation a generic, overridable view
47
- * concern rather than something baked into one specific adapter.
48
- * - **No orchestrator hook was needed.** Unlike the connectors canary
49
- * (`useConnectorCatalog`/`useConnectorAuthorization`/`useConnectorDetail`),
50
- * this feature has no live data-fetching or async state of its own —
51
- * `ProgressCard` is purely presentational, and the adapters are synchronous
52
- * pure functions. There is deliberately no `ports.ts`/`dependencies.ts`
53
- * pair in this feature; a host wires its own data source directly into
54
- * `ProgressCardData` (via these adapters or its own mapping) rather than
55
- * this package owning any transport.
56
- *
57
- * ### Dropped, and why
58
- *
59
- * - **The Bash `rm`-command detection heuristic** from the source
60
- * `deriveFileOps` (`extractSimpleBashDeletes`/`shellWords`/
61
- * `isShellSeparator`/`isRedirectionOperator`/`looksUnsafeForFileList`, ~100
62
- * lines) — a self-contained shell-command tokenizer used only to detect
63
- * file deletions performed via a raw `Bash` tool call rather than a
64
- * dedicated `Delete`-family tool. This is a distinct, non-trivial parsing
65
- * concern in its own right, not core to "progress bar + status icon + step
66
- * list," and isn't mentioned anywhere in r6 §1.5 or the plan doc's item 2.
67
- * `deriveFileOpsFromAgentEvents` keeps the tool-name-based classification
68
- * (`Read`/`Write`/`Edit`/`MultiEdit`/`Delete`/etc., which covers the large
69
- * majority of real file-op tool calls) and drops only the Bash-string
70
- * heuristic. A future task adopting this as a real extraction target should
71
- * do so as its own item, not bundled here.
72
- * - **`job.kind`** (`generation`/`revision`/`token-contract-rebuild`) was not
73
- * carried into `DesignSystemGenerationJobLike`/`ProgressCardData` at all —
74
- * it exists purely to drive the OD-branded, kind-specific copy the generic
75
- * title/detail design above already excludes. A host that wants
76
- * kind-specific text computes it itself before calling the adapter and
77
- * overrides `title`/`detail` on the result.
78
- * - **`todo.activeForm`** (an alternate in-progress-tense label OD's todo
79
- * schema carries) — not used by either card's actual rendering, so not
80
- * carried into `TodoItemLike`.
81
- * - **CSS class names were not ported verbatim** (`ds-workspace-activity-card`,
82
- * `ds-generation-review-card`, `ds-generation-review-progress`, etc.) — new,
83
- * neutral names were used (`progress-card`, `progress-card-bar`,
84
- * `progress-card-steps`, `progress-card-secondary-items`) since the
85
- * original classes are tied to OD's own stylesheet, not shipped here.
86
- *
87
- * ### Post-merge audit pass (2026-07-17): a real bug fix, a dead-code removal, and 100% coverage
88
- *
89
- * A follow-up audit re-diffed every in-scope piece above against the vendored
90
- * original function-by-function and found the port faithful — every
91
- * generification already listed in this section checked out against the
92
- * original's actual behavior. The audit did surface two real issues once
93
- * branch-coverage was wired up (`@vitest/coverage-v8`, run via a scoped CLI
94
- * include/exclude filter — `--coverage.include='src/features/browser-chrome/**'`
95
- * — rather than a shared `vitest.config.ts` change, so the rest of the package's
96
- * test config is untouched):
97
- *
98
- * - **Real bug, fixed** — `rules.ts`'s `recordNavigation` hardcoded
99
- * `DEFAULT_HOME_NAVIGATION_ENTRY.title` ("New Tab") for a navigation to
100
- * `EMPTY_URL`, ignoring a caller-supplied `options.homeLabel`. Since
101
- * `useBrowserNavigationStack` passes `homeLabel: homeEntry.title` on every
102
- * call, a host configuring a custom `homeEntry` would see any navigation back
103
- * to the home url silently retitle itself to the generic default instead of
104
- * the host's own label — a regression relative to `initialNavigationState`/
105
- * `labelFromUrl`, which both already honored a custom home label correctly.
106
- * Fixed to `options.homeLabel ?? DEFAULT_HOME_NAVIGATION_ENTRY.title`; covered
107
- * by new `rules.test.ts`/`useBrowserNavigationStack.test.ts` cases.
108
- * - **Dead code, removed** — `MergeHistoryEntryOptions.homeLabel` (threaded
109
- * through `mergeHistoryEntry` → `useBrowserHistory`'s `commitVisit`) could
110
- * never actually affect anything: `mergeHistoryEntry` only calls
111
- * `labelFromUrl` after its own `isHistoryUrl(url)` guard has already excluded
112
- * `EMPTY_URL`, and `homeLabel` only changes `labelFromUrl`'s output on the
113
- * `url === EMPTY_URL` branch. Removed the field from `MergeHistoryEntryOptions`
114
- * and `UseBrowserHistoryOptions` rather than leaving a permanently-uncovered,
115
- * inert option in the public API.
116
- * - **One line excluded from coverage, not faked** —
117
- * `useBrowserNavigationStack.ts`'s `if (!currentEntry) return;` guard inside
118
- * the `onNavigate`-firing effect was unreachable through the hook's public
119
- * API: every state transition it performs (`initialNavigationState`/
120
- * `recordNavigation`/`resolveNavigationHistoryDelta`/
121
- * `updateCurrentNavigationTitle`, all in `rules.ts`) preserves
122
- * `0 <= navigationIndex < navigationStack.length`, so `currentEntry` is always
123
- * defined in practice — the guard existed only because
124
- * `noUncheckedIndexedAccess` types the array-index read as possibly-undefined.
125
- * **Correction (2026-07-17, per the vendored `fixing-open-design-web` SKILL.md's
126
- * Phase 9.5 classification #4 — "TS-required fallback with no real runtime
127
- * path"):** an initial pass marked this with `/* v8 ignore next * /`, which
128
- * that skill's rule explicitly forbids ("never a valid outcome... under any
129
- * classification"). Fixed to the classification's actual prescription: the
130
- * `if` branch is deleted and the index read is a non-null assertion
131
- * (`state.navigationStack[state.navigationIndex]!`) with a one-line comment
132
- * explaining the invariant — no suppression comment anywhere in this feature.
133
- * - **`ports.ts`/`types.ts` excluded from coverage** — both are
134
- * `export interface`/`export type` only; verified via the package's own
135
- * esbuild transform that they compile to zero emitted statements, so
136
- * v8/istanbul has no executable line to measure (reports 0/0 as 0%, not N/A).
137
- * Excluded via `--coverage.exclude`, documented inline at the top of each
138
- * file. `index.ts` (the barrel) is NOT excluded — it has real re-export
139
- * statements that execute on import, and nothing else in the suite imported
140
- * the barrel directly, so a small `index.test.ts` smoke test was added instead
141
- * (also catches a typo'd/missing re-export a concrete-module test wouldn't).
142
- *
143
- * Also closed several genuine (non-dead) branch-coverage gaps with targeted
144
- * tests rather than exclusions: `recordNavigation`'s adjacent-entry rejoin and
145
- * `replacePendingTarget` branches (the back/forward state-machine logic
146
- * faithfully ported from the origin, previously untested); `recordNavigation`/
147
- * `updateCurrentNavigationTitle` given an out-of-bounds `navigationIndex` (both
148
- * are exported pure functions, so a malformed `BrowserNavigationState` is a
149
- * legitimately reachable input, not hook-internal dead code); `faviconUrl`'s
150
- * catch branch (`https://` with no host); `labelFromUrl`'s empty-hostname
151
- * fallback (`file://` urls); `cleanIconUrl`'s `data:image/` branch; the
152
- * `onNavigate` dedup-by-content check (a re-recorded identical url+title still
153
- * produces a new object reference via `updateEntry`, so the effect re-runs and
154
- * must dedupe on content, not just skip via unchanged reference);
155
- * `BrowserViewportControls`'s custom-`presets`-with-no-match and empty-`presets`
156
- * branches; and `createDefaultBrowserChromeDependencies`'s `historyLimit`-only
157
- * option combination.
158
- *
159
- * **Result**: feature-aggregate coverage on the executable-code portion (i.e.
160
- * excluding `ports.ts`/`types.ts` per above) is **100% Lines, 100% Branches,
161
- * 100% Functions, 100% Statements** — up from 99.15% / 87.77% / 97.56% / 99.15%
162
- * before this pass. Full suite: 101 tests across 7 files for this feature (up
163
- * from 78), 476 tests across 60 files package-wide (up from 453).
164
- * `pnpm --filter @jini/ui run typecheck` and `pnpm guard` both remain clean.
165
- *
166
- * ### Second follow-up pass (2026-07-17): `useX`/`useWiredX` wiring pairs, toolbox merge
167
- *
168
- * Two retrofits landed on this branch after the audit pass above:
169
- *
170
- * **`useWiredX` wirers.** Per the now-required `useX(port)` / zero-arg
171
- * `useWiredX()` pattern (see `apps/web/src/features/memory/hooks/
172
- * useMemoryConfig.hooks.ts` on the OD repo's `refactor/web-memory-slice` for
173
- * the reference shape), audited every hook in this feature against
174
- * `ports.ts`/`dependencies.ts` to see which actually take an injected port:
175
- *
176
- * - `useBrowserHistory` (takes `{ historyStorage: BrowserHistoryStoragePort }`)
177
- * — got `useWiredBrowserHistory(scopeKey, options?)`, binding a module-level
178
- * `createBrowserHistoryStorage()` singleton (the real, SSR-guarded
179
- * `localStorage`-backed implementation — a meaningful production default).
180
- * - `useBrowserBridgeRegistration` (takes `{ bridgeRegistration:
181
- * BrowserBridgeRegistrationPort }`) — got `useWiredBrowserBridgeRegistration
182
- * (scopeKey, handle)`, binding `createNoopBrowserBridgeRegistration()`.
183
- * Unlike the history port, there's no generic "real" default here by design
184
- * (see `ports.ts`'s doc comment) — registering a handle only means something
185
- * in the context of a host's own external bridge. A host that wants real
186
- * bridge registration keeps calling `useBrowserBridgeRegistration` directly
187
- * with its own port, same carve-out as a swappable test port, just for a
188
- * real host implementation instead of a fake.
189
- * - `useBrowserNavigationStack` — **no wirer added.** Its `options` (`initialUrl`/
190
- * `initialTitle`/`homeEntry`/`onNavigate`) are all plain local config, not a
191
- * `ports.ts` port; the hook owns its state entirely via `rules.ts`'s pure
192
- * functions. Nothing to wire.
193
- *
194
- * Both wirers exported from `index.ts`; no internal call sites needed updating
195
- * — this feature has no top-level assembling component (that lives in the
196
- * consuming host, out of scope per this feature's own "OUT OF SCOPE" section
197
- * above), so `useBrowserHistory`/`useBrowserBridgeRegistration` had zero
198
- * in-package callers before or after.
199
- *
200
- * **Toolbox merge.** Merged local branch `feat/ui-browser-toolbox` (commit
201
- * `c3e7f21`, not pushed to origin) — a clean merge, no conflicts (it branched
202
- * off a commit before `features/browser-chrome/` existed, so it never touched
203
- * this feature's files). It adds `packages/ui/src/browser/` (`useDismissOnOutsideOrEscape`,
204
- * `useGlobalKeydown`) as a thin wrapper over `utils/dom-subscriptions.ts`'s
205
- * `subscribeOutsideClickOrEscape`. `BrowserViewportControls.tsx`'s hand-rolled
206
- * `document.addEventListener('pointerdown'/'keydown', ...)` pair (the one
207
- * disclosed DOM-outside-`dependencies.ts` deviation noted earlier in this
208
- * section) is now `useDismissOnOutsideOrEscape(() => setOpen(false), { enabled:
209
- * open, containerRef: menuRef })` — same `pointerdown`-outside-or-Escape
210
- * behavior, dead local listener code removed. All of `BrowserViewportControls.test.tsx`'s
211
- * existing outside-click/Escape assertions pass unchanged against the shared
212
- * hook, confirming no behavior change.
213
- *
214
- * **Result**: still 100% Lines/Branches/Functions/Statements on the
215
- * executable-code portion after both retrofits (wirers came with their own
216
- * tests; the toolbox swap needed none new since it's a drop-in behind the same
217
- * public component API). 103 tests across 7 files for this feature; 494 tests
218
- * across 62 files package-wide (the toolbox branch's own `useDismissOnOutsideOrEscape.test.ts`/
219
- * `useGlobalKeydown.test.ts` account for the rest of the file-count jump).
220
- * `pnpm --filter @jini/ui run typecheck` and `pnpm guard` both remain clean.
221
- *
222
- * ---
223
- *
224
- * ### What did NOT get ported (and why)
225
- *
226
- * - **No `ports.ts`/`dependencies.ts`.** Unlike every other feature in this
227
- * package, `ListDetailPanel` has zero transport/DOM surface of its own — the
228
- * host supplies items, the current selection, and both renderers as plain
229
- * props/render-callbacks. There is nothing here for a port to abstract; the
230
- * DI-seam ceremony would be empty ceremony for a purely presentational
231
- * primitive, so it was skipped rather than added for form's sake.
232
- * - **No visual skeleton markup.** `DesignSystemsTab.tsx`'s loading state is a
233
- * richly detailed, OD-styled skeleton (specific row-variation patterns, a
234
- * multi-section detail skeleton with its own CSS module). Per this package's
235
- * established precedent (no `.module.css` ported anywhere in `@jini/ui` —
236
- * see the flat-group porting section above), the loading state is generified
237
- * to `loading` + `loadingSidebarContent`/`loadingDetailContent` slots; a host
238
- * supplies its own skeleton visuals. The panel's only built-in loading-state
239
- * contribution is the `role="status" aria-busy aria-label` wrapper.
240
- * - **Analytics, i18n dictionary keys, scope/surface/category filtering,
241
- * `SystemRow`'s thumbnail-resolution logic, publish/delete/make-default
242
- * actions** — all OD-specific, stay in OD.
243
- *
244
- * ### The root-level "flattened tree" quirk — verified, not assumed, and preserved
245
- *
246
- * `deriveTreeChildren` preserves a genuinely surprising piece of the origin's own `dirsAtCurrentDir`/`filesAtCurrentDir` `useMemo` verbatim: at the tree root (`currentDir === ''`), **every** file is pushed into `filesAtCurrentDir` — both root-level files and files nested under a subdirectory (which *also* separately contribute their top segment to `dirsAtCurrentDir`) — so the root view is a flattened "everything" listing with folders offered only as a secondary drill-down. Once navigated into any non-root directory, only files strictly at that one level are included. This asymmetry looked enough like a bug to warrant re-reading the real source line-by-line before committing to it (per the task's own "don't trust it blindly" instruction) — but it's exactly what the code does, so it's preserved rather than "fixed," with a `rules.test.ts` case asserting it explicitly (`'at the root, flattens every file (including nested) and surfaces the top-level dir'`).
247
- *
248
- * ### Where it landed, and why (`packages/ui/src/features/memory/`, not `chat-react`)
249
- *
250
- * Per `ADS-memory/reports/jini-port/god-components-extraction-plan.md`'s Consolidation map and
251
- * `packages/ui/README.md`'s scope boundary: Memory is a settings/data-management
252
- * surface (saved facts/preferences, an editable index, connector-sourced
253
- * suggestions) — the same shape as the already-shipped `features/connectors/` and
254
- * `features/settings-dialog/`, not a conversation surface. It lands alongside them
255
- * in `@jini/ui`, using the **new** `types.ts`/`constants.ts`/`rules.ts`/`ports.ts`/
256
- * `dependencies.ts`/`formatters.ts`/`async-commit-guard.ts`/`index.ts` at the
257
- * feature's top level, `hooks/`+`components/` under a `react/` subfolder — the
258
- * layout decided 2026-07-17, matching `features/viewer-shell/`/`features/asset-grid/`/
259
- * `features/sketch-editor/`, not `features/connectors/`'s older flat layout.
260
- *
261
- * ### The connector-reconciliation-reducer decision (the "third piece")
262
- *
263
- * The task brief's third sought piece — "connector-reconciliation reducers" — does
264
- * **not** come from PR #5228. Its real origin is Open Design's `main`-branch
265
- * `apps/web/src/components/connectors-state.ts` (confirmed by cloning
266
- * `https://github.com/leonaburime-ucla/open-design.git` at its default `main`
267
- * branch and reading `connectors-state.ts` directly, since `codex/connector-memory-settings`,
268
- * the branch originally suspected to hold this, diffs empty against current `main`
269
- * — i.e. that logic already lives on `main` by some other route). Its 4 functions
270
- * — `connectorAuthSnapshotChanged`/`hasConnectorStatusChanges`/`mergeConnectorCatalog`/
271
- * `applyConnectorStatuses` — are a **separate, shared/generic** connector-list
272
- * reconciliation module OD's `MemorySection.tsx` monolith imports directly
273
- * (`import { hasConnectorStatusChanges } from './connectors-state'`), distinct from
274
- * PR #5228's own Memory-local `mergeMemoryConnector`/`upsertMemoryConnector`/
275
- * `applyMemoryConnectorStatus(es)`/`connectorStatusesChanged` (which the PR's own
276
- * `rules.ts` comment calls "convenience duplication" of the shared module, kept
277
- * slice-local per the PR's own stated slice conventions).
278
- *
279
- * Direct line-by-line comparison found `@jini/ui`'s `features/connectors/rules.ts`
280
- * **already ships the generified port of `connectors-state.ts`** — from the
281
- * `ConnectorsBrowser.tsx` canary task (2026-07-17), see that section above —
282
- * as `mergeConnectors`/`applyConnectorStatuses`/`hasConnectorStatusChanges`/
283
- * `connectorAuthSnapshotChanged`, operating on the generic `Connector`/
284
- * `ConnectorStatusMap` types instead of OD's `ConnectorDetail`. Their logic is
285
- * identical to `connectors-state.ts`'s (verified field-by-field), and `mergeConnectors`
286
- * already subsumes what PR #5228's `mergeMemoryConnector`+`upsertMemoryConnector`
287
- * did (single-connector merge + array upsert in one pass). This is exactly the
288
- * overlap `god-components-extraction-plan.md`'s Consolidation map flagged in
289
- * advance: *"Memory slice's connector reducers... substantially overlap
290
- * `features/connectors`'... check whether it can import these directly instead of
291
- * re-deriving equivalents."*
292
- *
293
- * **Decision**: `features/memory/rules.ts` imports `mergeConnectors`/
294
- * `applyConnectorStatuses`/`hasConnectorStatusChanges` from `../connectors` and
295
- * re-exposes two thin, Memory-specific conveniences over them
296
- * (`upsertMemoryConnector` = `mergeConnectors(current, next ? [next] : [])`;
297
- * `applyMemoryConnectorStatus` = the 1-item form of `applyConnectorStatuses`, used
298
- * by the synthetic not-yet-detailed catalogue row). Only `connectorWithPendingAuthorization`
299
- * (no equivalent in `features/connectors`) is genuinely new Memory-local logic.
300
- * Memory's own connector type is `Connector` from `features/connectors/types.ts`
301
- * directly (not a third near-duplicate of `ConnectorDetail`) — its shape already
302
- * matches (id/name/provider/category/status/accountLabel/lastError/tools/toolCount/
303
- * toolsNextCursor/toolsHasMore/logoUrl).
304
- *
305
- * ### The consolidation decision: ONE primitive, with evidence
306
- *
307
- * Read both in full before designing anything, per the task brief. Verdict:
308
- * **consolidate into one `FileDropzone` primitive** — not two components
309
- * sharing a subdirectory, one component with configuration knobs. Evidence:
310
- *
311
- * 1. **Both are the exact same underlying interaction** — native drag/drop +
312
- * click-to-browse, resolving to a flat `File[]` the host stages. The only
313
- * real differences are *display* (thumbnail grid + lightbox vs. a plain
314
- * prompt/names line) and which capabilities are wired on (paste,
315
- * directory-select, the loading heuristic) — configuration, not a different
316
- * component shape.
317
- * 2. **They already shared the same directory-walking algorithm at the OD
318
- * source level**, just wired at different layers: `DropZone`'s `readDrop`
319
- * calls `filesFromDataTransfer` (a `webkitGetAsEntry` recursive directory
320
- * walker) internally before calling `onFiles`; `DesignSystemAssetDropzone`'s
321
- * `onDrop` prop just hands the raw `DataTransfer` up to its parent
322
- * (`DesignSystemFlow.tsx`'s `handleAssetDrop`), which calls the **exact
323
- * same** `filesFromDataTransfer` function (same file, one module-level
324
- * definition) before staging. One algorithm, two wiring styles — a textbook
325
- * case for one primitive owning it internally always, which is what this
326
- * port does (both variants now get directory-aware drop resolution for
327
- * free, including the thumbnail-grid variant, which never had it before).
328
- * 3. **A duplicate of that same algorithm already existed a third time in this
329
- * package** — `features/asset-tree-browser/rules.ts`'s `filesFromDataTransfer`
330
- * (ported earlier from `DesignFilesPanel.tsx`, already fully generic). This
331
- * is exactly the failure mode flagged by an independent audit the night
332
- * this task was dispatched ("an undetected duplicate primitive") — so
333
- * rather than writing a *fourth* copy for `file-dropzone`, this task
334
- * promotes the shared logic to `utils/file-transfer.ts` (see below) and
335
- * both features now import the one implementation.
336
- *
337
- * ### What's deferred, and why
338
- *
339
- * Per the `html-viewer` classification above: the sandboxed-iframe/postMessage-bridge core this feature's `resolvePreviewDocument` port is designed to eventually delegate to (`@jini/renderers-react`, currently a stub) does not exist yet. This feature does **not** wait on it — a host without a real sandbox core can implement `resolvePreviewDocument` as an identity function for a plain, unsandboxed preview, or delegate to whatever iframe-rendering mechanism it already has.
340
- *
341
- * **Update (2026-09-02):** this was accurate when written, but the same day
342
- * (2026-07-18) a parallel task landed the real sandboxed-iframe/postMessage
343
- * core (see `packages/ui/src/renderers/archived provenance ledger`'s "sandboxed-iframe
344
- * rendering core" section) — it now exists (`sandbox-bridge.ts`,
345
- * `sandboxed-document.ts`), and the package itself was later folded into
346
- * `@jini/ui` as `src/renderers/` rather than staying a separate
347
- * `@jini/renderers-react` package. The default fake dependency here
348
- * (`features/version-manager/dependencies.ts`) still uses a plain identity
349
- * stub for `resolvePreviewDocument` — that's an intentional default per the
350
- * fake-double convention, not evidence the real core is missing — a host
351
- * wanting the real sandbox behavior wires it to `src/renderers/` itself. `FileVersionViewportControls` was not re-ported; the orchestrator binds directly to `features/viewer-shell/`'s already-shipped `ViewportToggleGroup` (confirmed identical `role="group"`/`aria-pressed` shape by reading both source components side by side) rather than shipping a second, competing viewport-toggle primitive.
352
- *
353
- * ### A real cross-environment coverage-merge gap found and worked around
354
- *
355
- * Drafting `dependencies.ts`'s tests initially split them the way this
356
- * package's own documented convention prescribes for an SSR guard: a jsdom
357
- * test file for the "browser present" cases plus a separate
358
- * `// @vitest-environment node` companion for the "no `document` at all"
359
- * case. Coverage on the merged report showed that one guard's branch
360
- * (`typeof document === 'undefined'` in `exitFullscreen`) as **uncovered**
361
- * even though the node companion file, run alone, proved it covered — a real
362
- * `@vitest/coverage-v8` limitation merging branch-hit counts for one source
363
- * file instrumented under two different test environments in the same
364
- * `vitest run`. Fixed by moving every `createBrowserFullscreenPort` test
365
- * into a single `// @vitest-environment node` file, using a hand-built fake
366
- * `document` (a real `EventTarget` plus the two Fullscreen-API members this
367
- * port reads) for the "document present" cases instead of jsdom's real
368
- * global — eliminating the environment split (and the merge gap with it)
369
- * rather than leaving a genuinely-tested branch looking uncovered in the
370
- * aggregate. Worth flagging for any future task in this package relying on
371
- * the jsdom-file-plus-node-companion pattern for an SSR guard: verify the
372
- * *merged* per-file coverage, not just the companion file's own isolated
373
- * number, before trusting it clears the bar.
374
-
375
- * Archived provenance rationale:
376
- * ## Merge note (2026-07-18): reconciling with `port/renderers-react-and-annotation-canvas`
377
- *
378
- * This branch (`feature/jini-ui-html-viewer`) and `port/renderers-react-and-annotation-canvas`
379
- * (merged to `main` first) both independently built a sandboxed-iframe HTML
380
- * rendering core in this package, from the same OD origin file
381
- * (`runtime/srcdoc.ts`), without either branch seeing the other's work. On
382
- * merge, both cores are kept side by side rather than one replacing the
383
- * other, since `@jini/ui`'s `features/html-viewer` (this branch) is a real,
384
- * already-wired consumer of the `sandboxed-document.ts`/`sandbox-bridge.ts`/
385
- * `new-tab-preview.ts` core (`useSandboxBridge`, `openSandboxedPreviewInNewTab`),
386
- * while the `srcdoc/build.ts` core is the one wired into `buildSrcDoc`,
387
- * `SrcDocBridge`, `ArtifactView`, and the annotation-canvas integration above.
388
- *
389
- * The two cores' public surfaces are disjoint by name **except** for three
390
- * generic string-splice helpers both sides ported from the same origin
391
- * function shape: `injectAfterHeadOpen`, `injectBeforeHeadEnd`,
392
- * `injectBeforeBodyEnd`. They are not behaviorally identical — `srcdoc/
393
- * build.ts`'s versions add a `DOMParser`-based fallback for documents with no
394
- * matching `<head>`/`<body>` tag at all, which `html-utils.ts`'s versions
395
- * (deliberately, per `sandboxed-document.ts`'s own already-tested contract)
396
- * resolve via a plain string prepend/append instead. Both fallback behaviors
397
- * are real, disclosed, and independently test-covered (`html-utils.test.ts`
398
- * vs. `srcdoc/build.test.ts`'s "falls back to DOMParser" cases), so rather
399
- * than pick a winner, `srcdoc/build.ts`'s versions keep their original names
400
- * in the public barrel (`src/index.ts`) as the canonical/more broadly-used
401
- * ones, and `html-utils.ts`'s versions are re-exported under an
402
- * `injectAfterHeadOpenStringOnly`/`injectBeforeHeadEndStringOnly`/
403
- * `injectBeforeBodyEndStringOnly` alias. Neither implementation changed;
404
- * `sandboxed-document.ts` still imports its own `html-utils.ts` internally
405
- * under the original names, unaffected by the barrel-level alias.
406
- *
407
- * No other real naming collisions were found between the two cores'
408
- * `package.json`, `types.ts`, or barrel exports — `package.json`'s
409
- * dependency/devDependency lists were a union merge (both sides' React
410
- * version pins already matched); `types.ts`'s two additions
411
- * (`SandboxedDocumentOptions`/`SandboxedDocumentResult`/`SandboxBridgeMessage`/
412
- * `SandboxBridgeHandler` from this branch, `ArtifactFile` + the `@jini/
413
- * chat-core` manifest-vocabulary re-exports from `port/renderers-react-and-
414
- * annotation-canvas`) are simply concatenated, not merged shape-for-shape,
415
- * since neither side redeclares anything the other already had.
416
- *
417
- * ---
2
+ * @module @jini-ai/ui — product-neutral UI primitives and feature surfaces.
3
+ *
4
+ * Presentation and ownership:
5
+ * - Progress-card copy is host-supplied because job kinds and branded messages
6
+ * belong to the product. Neutral status defaults and accessibility labels are
7
+ * translated; dynamic item labels are already host content and are not.
8
+ * - Progress supports determinate and indeterminate work. Adapters return full
9
+ * lists; display caps belong to the component so source data stays complete.
10
+ * Structural adapter inputs avoid a dependency on any product's DTO package.
11
+ * - ProgressCard and ListDetailPanel are presentational: hosts supply data,
12
+ * selection, renderers, loading slots and visual styling. Transport ports
13
+ * would have no behavior to abstract. Product analytics, filtering and actions
14
+ * stay with the host. File-operation adapters classify tool names; shell-command
15
+ * parsing is a separate concern, not part of the progress display.
16
+ * - Browser history has a real, SSR-safe storage default. Bridge registration
17
+ * defaults to a no-op because only a host can define its external bridge.
18
+ * Navigation-stack configuration is local state, so it needs no port wirer.
19
+ * Outside-click/Escape subscriptions belong to the shared browser hooks.
20
+ * - Asset-tree root listings intentionally include nested files alongside
21
+ * drill-down folders; non-root listings contain only the current directory.
22
+ * This asymmetry is part of the existing tree contract, not an accidental
23
+ * omission of root filtering.
24
+ * - Memory is a settings/data-management surface, not chat. Connector catalog
25
+ * reconciliation and connector types belong to features/connectors; memory
26
+ * adds only its own pending-authorization and single-item conveniences.
27
+ * - FileDropzone owns native browse/drop/paste interactions and their display
28
+ * variants. Directory walking and file-transfer logic live in utils/file-transfer
29
+ * so dropzones and asset trees share one implementation.
30
+ *
31
+ * Rendering contracts:
32
+ * - Hosts opt into real sandbox behavior for version-manager previews through
33
+ * resolvePreviewDocument. Its identity fake is a dependency default, not a
34
+ * claim that the renderer core is missing. Viewport toggles reuse viewer-shell.
35
+ * - sandboxed-document and srcdoc/build have distinct builder and bridge
36
+ * contracts. The canonical splice helpers come from srcdoc/build and can fall
37
+ * back to DOMParser; the StringOnly aliases preserve html-utils' prepend/append
38
+ * fallback. Choosing one fallback for both would change public behavior.
39
+ *
40
+ * Heavy editors use dedicated @jini-ai/ui/sketch-editor and
41
+ * @jini-ai/ui/lexical-rich-text-editor entries so ordinary root imports do not
42
+ * load their editor dependencies. See packages/ui/README.md for package scope.
418
43
  */
419
44
  export * from './features/i18n/index.js';
420
45
  export * from './features/admin-widgets/index.js';
@@ -478,7 +103,7 @@ export * from './react/hooks/useBrandFonts.js';
478
103
  export * from './react/hooks/useEdgeAutoScroll.js';
479
104
  export * from './browser/useModalWindowDragGuard.js';
480
105
  export * from './browser/index.js';
481
- export { Icon, type IconName } from './react/components/Icon.js';
106
+ export { Icon, ICON_PATH_DATA, type IconName } from './react/components/Icon.js';
482
107
  export * from './react/components/RemixIcon.js';
483
108
  export * from './react/components/AgentIcon.js';
484
109
  export * from './react/components/Toast.js';