@lapismd/design-core 0.1.0 → 0.2.0
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.
- package/CHANGELOG.md +44 -0
- package/LICENSE.md +3 -3
- package/README.md +21 -1
- package/package.json +34 -15
- package/spec/src/styling-and-themes.md +11 -9
- package/src/shared/ai/chat.css +25 -1
- package/src/shared/ai/chat.ts +12 -0
- package/src/shared/ai/composer-input/ComposerInput.svelte +3 -2
- package/src/shared/ai/context.svelte.ts +2 -0
- package/src/shared/ai/experimental/reaction-bar/ReactionBar.svelte +1 -1
- package/src/shared/ai/layout/Layout.svelte +116 -10
- package/src/shared/ai/message-list/MessageList.svelte +123 -43
- package/src/shared/ai/message-list/MessageListHistoryFixture.svelte +112 -0
- package/src/shared/ai/message-list/MessageListLegacyFixture.svelte +52 -0
- package/src/shared/ai/message-list/VirtualizedMessageRows.svelte +299 -0
- package/src/shared/ai/message-list/position.ts +7 -0
- package/src/shared/ai/new-messages.svelte.ts +24 -5
- package/src/shared/ai/stream-scroll.svelte.ts +135 -6
- package/src/shared/ai/tool-call-detail/ToolCallDetail.svelte +71 -0
- package/src/shared/ai/tool-call-detail/tool-call-detail.ts +209 -0
- package/src/shared/ai/tool-calls/ToolCalls.svelte +1 -1
- package/src/shared/ai/trigger-menu.ts +2 -3
- package/src/shared/diff/core/merge/actions.ts +4 -3
- package/src/shared/diff/core/merge/render-model.ts +14 -10
- package/src/shared/diff/file-diff/FileDiff.css +68 -1
- package/src/shared/diff/file-diff/FileDiff.svelte +27 -14
- package/src/shared/diff/file-diff/FileDiffComposer.svelte +98 -16
- package/src/shared/diff/file-diff/index.ts +2 -0
- package/src/shared/diff/file-diff/types.ts +13 -0
- package/src/shared/diff/file-listing/FileListingViewModeToggle.css +42 -5
- package/src/shared/diff/index.ts +2 -0
- package/src/shared/diff/merge-editor/MergeEditor.svelte +2 -7
- package/src/shared/filter/filter-query/filters.ts +2 -2
- package/src/shared/filter/filter-query/parser.ts +9 -8
- package/src/shared/filter/power-search/PowerSearch.svelte +1 -1
- package/src/shared/filter/search-filter-bar/SearchFilterBar.svelte +2 -2
- package/src/shared/filter/search-filter-bar/SearchFilterInput.svelte +1 -1
- package/src/shared/filter/search-filter-bar/SearchFilterPredicateEditor.svelte +1 -1
- package/src/shared/filter/search-filter-bar/search-filter-syntax.ts +1 -1
- package/src/shared/forms/autocomplete-input/AutocompleteInput.svelte +19 -7
- package/src/shared/forms/confirm-button/ConfirmButton.svelte +38 -0
- package/src/shared/forms/confirm-button/ConfirmButtonExample.svelte +14 -0
- package/src/shared/forms/confirm-button/index.ts +1 -0
- package/src/shared/forms/confirm-dialog/ConfirmDialog.css +21 -0
- package/src/shared/forms/confirm-dialog/ConfirmDialog.svelte +116 -0
- package/src/shared/forms/confirm-dialog/ConfirmDialogExample.svelte +17 -0
- package/src/shared/forms/confirm-dialog/index.ts +2 -0
- package/src/shared/forms/dialog-frame/DialogFrame.css +130 -0
- package/src/shared/forms/dialog-frame/DialogFrame.svelte +108 -0
- package/src/shared/forms/dialog-frame/DialogFrameExample.svelte +37 -0
- package/src/shared/forms/dialog-frame/index.ts +6 -0
- package/src/shared/forms/dialog.ts +8 -0
- package/src/shared/forms/index.ts +11 -0
- package/src/shared/shadcn/button/button.svelte +4 -0
- package/src/shared/shadcn/code-block/highlightRanges.ts +10 -6
- package/src/shared/shadcn/code-block/syntax/defineSyntaxTheme.ts +4 -2
- package/src/shared/shadcn/code-block/tokenizer.ts +3 -3
- package/src/shared/shadcn/command/command-dialog.svelte +1 -1
- package/src/shared/shadcn/command/command-group.svelte +3 -1
- package/src/shared/shadcn/command-view/command-view.svelte +1 -6
- package/src/shared/shadcn/dialog/dialog-content.svelte +3 -4
- package/src/shared/shadcn/dialog/dialog-portal.svelte +10 -2
- package/src/shared/shadcn/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -691
- package/src/shared/shadcn/dropdown-menu/dropdown-menu-content.svelte +691 -0
- package/src/shared/shadcn/dropdown-menu/dropdown-menu-radio-group.svelte +1 -1
- package/src/shared/shadcn/scroll-area/scroll-area.svelte +2 -0
- package/src/shared/shadcn/spinner/spinner.svelte +3 -3
- package/src/shared/shadcn/tooltip/tooltip-content.svelte +10 -4
- package/src/shared/shadcn/tooltip/tooltip.tokens.ts +4 -0
- package/src/shared/shell/app-shell/AppShell.css +112 -32
- package/src/shared/shell/app-shell/AppShell.demo.css +37 -0
- package/src/shared/shell/app-shell/AppShellBodyContent.svelte +5 -1
- package/src/shared/shell/app-shell/AppShellBodySidebar.svelte +5 -1
- package/src/shared/shell/app-shell/AppShellMain.svelte +12 -1
- package/src/shared/shell/app-shell/AppShellMobilePanelSelector.svelte +1 -1
- package/src/shared/shell/app-shell/AppShellRoot.svelte +27 -13
- package/src/shared/shell/app-shell/AppShellSidebar.svelte +121 -19
- package/src/shared/shell/app-shell/AppShellSidebarClose.svelte +17 -17
- package/src/shared/shell/app-shell/AppShellSidebarToggle.svelte +38 -58
- package/src/shared/shell/app-shell/AppShellSurfaceLayer.svelte +173 -0
- package/src/shared/shell/app-shell/AppShellSurfaceLayerBody.svelte +32 -0
- package/src/shared/shell/app-shell/AppShellSurfaceLayerHeader.svelte +26 -0
- package/src/shared/shell/app-shell/app-shell-context.svelte.ts +6 -3
- package/src/shared/shell/app-shell/app-shell-controller.svelte.ts +269 -11
- package/src/shared/shell/app-shell/app-shell-sidebar-context.svelte.ts +1 -0
- package/src/shared/shell/app-shell/examples/AppShellBodyDemo.svelte +4 -0
- package/src/shared/shell/app-shell/examples/AppShellCompleteDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellConversationDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellExamples.css +624 -0
- package/src/shared/shell/app-shell/examples/AppShellFilesSidebarDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellMarkdownDocumentDemo.svelte +6 -1
- package/src/shared/shell/app-shell/examples/AppShellMarkdownFilesDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellModeSwitchDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellMultiPanelDemo.svelte +187 -0
- package/src/shared/shell/app-shell/examples/AppShellProjectSidebarDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellSidebarDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellToolbarDemo.svelte +1 -0
- package/src/shared/shell/app-shell/index.ts +14 -0
- package/src/shared/shell/shell.tokens.css +2 -0
- package/src/shared/shell/shell.tokens.ts +5 -0
- package/src/shared/workspace/menu/WorkspaceContextMenuItems.svelte +2 -1
- package/src/shared/workspace/menu/WorkspaceMenuItems.svelte +2 -1
- package/src/shared/workspace/problems/ProblemsQuickFix.svelte +1 -4
- package/src/shared/workspace/settings/AppSettingsContent.svelte +6 -0
- package/src/shared/workspace/settings/AppSettingsNavigation.svelte +7 -0
- package/src/shared/workspace/settings/CopyableValue.svelte +81 -0
- package/src/shared/workspace/settings/DeclarativeSettingsSection.svelte +20 -0
- package/src/shared/workspace/settings/WorkspaceSettingField.svelte +110 -41
- package/src/shared/workspace/settings/WorkspaceSettingMultiSelect.svelte +7 -6
- package/src/shared/workspace/settings/WorkspaceSettingObjectTable.svelte +187 -23
- package/src/shared/workspace/settings/WorkspaceSettingSelect.svelte +29 -29
- package/src/shared/workspace/settings/WorkspaceSettings.css +190 -4
- package/src/shared/workspace/settings/WorkspaceSettingsStoryCustomField.svelte +2 -2
- package/src/shared/workspace/settings/WorkspaceSettingsStoryCustomPage.svelte +13 -0
- package/src/shared/workspace/settings/WorkspaceSettingsSurface.svelte +50 -0
- package/src/shared/workspace/settings/configuration.ts +5 -0
- package/src/shared/workspace/settings/copyable-value.ts +10 -0
- package/src/shared/workspace/settings/index.ts +5 -0
- package/src/shared/workspace/settings/settings-controller.svelte.ts +349 -15
- package/src/shared/workspace/settings/types.ts +90 -8
- package/src/storybook/app-shell-reference/AppShellTwoExpandedSidebarsReference.css +25 -0
- package/src/storybook/app-shell-reference/AppShellTwoExpandedSidebarsReference.svelte +48 -0
- package/src/storybook/app-shell-reference/index.ts +1 -0
- package/src/theme.css +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @lapismd/design-core
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#7](https://github.com/lapismd/design-core/pull/7) [`737c657`](https://github.com/lapismd/design-core/commit/737c65727a6beaeb6955a652aba67c42b882b222) Thanks [@stevejuma](https://github.com/stevejuma)! - Add composable same-side App Shell panels, responsive main-surface replacement, transparent rails, external controller toggles, and structural surface layers.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#7](https://github.com/lapismd/design-core/pull/7) [`80937e0`](https://github.com/lapismd/design-core/commit/80937e0f01e8dda50cbbed45da4948736ec3035b) Thanks [@stevejuma](https://github.com/stevejuma)! - Relicense the published Design Core package to Apache 2.0.
|
|
12
|
+
|
|
13
|
+
- [#7](https://github.com/lapismd/design-core/pull/7) [`80937e0`](https://github.com/lapismd/design-core/commit/80937e0f01e8dda50cbbed45da4948736ec3035b) Thanks [@stevejuma](https://github.com/stevejuma)! - Tighten shared Tooltip padding and type so compact overlays no longer inherit oversized content chrome.
|
|
14
|
+
|
|
15
|
+
- [#7](https://github.com/lapismd/design-core/pull/7) [`80937e0`](https://github.com/lapismd/design-core/commit/80937e0f01e8dda50cbbed45da4948736ec3035b) Thanks [@stevejuma](https://github.com/stevejuma)! - Expose controlled multi-file review state, host-owned line annotations, leading file headers, and gutter line actions. Diff helpers stay compatible with strict TypeScript consumers.
|
|
16
|
+
|
|
17
|
+
- [#7](https://github.com/lapismd/design-core/pull/7) [`80937e0`](https://github.com/lapismd/design-core/commit/80937e0f01e8dda50cbbed45da4948736ec3035b) Thanks [@stevejuma](https://github.com/stevejuma)! - Keep mobile App Shell panels visible while focus moves between the trigger and the opened surface.
|
|
18
|
+
|
|
19
|
+
- [#7](https://github.com/lapismd/design-core/pull/7) [`80937e0`](https://github.com/lapismd/design-core/commit/80937e0f01e8dda50cbbed45da4948736ec3035b) Thanks [@stevejuma](https://github.com/stevejuma)! - Add opt-in `MessageList` virtualization while keeping the default unvirtualized chat layout. History scrolling now preserves user intent across measurements, state saves, and parent updates.
|
|
20
|
+
|
|
21
|
+
- [#7](https://github.com/lapismd/design-core/pull/7) [`80937e0`](https://github.com/lapismd/design-core/commit/80937e0f01e8dda50cbbed45da4948736ec3035b) Thanks [@stevejuma](https://github.com/stevejuma)! - Add shared dialog frames, inset large frames, and retryable confirmations. Portal updates keep dialog controls mounted, and dialog headings stay out of document landmarks.
|
|
22
|
+
|
|
23
|
+
- [#7](https://github.com/lapismd/design-core/pull/7) [`80937e0`](https://github.com/lapismd/design-core/commit/80937e0f01e8dda50cbbed45da4948736ec3035b) Thanks [@stevejuma](https://github.com/stevejuma)! - Export shared `ToolCallDetail` presentation so hosts can render tool payloads, summaries, and expandable detail without forking chat markup.
|
|
24
|
+
|
|
25
|
+
## 0.1.2
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- [#2](https://github.com/lapismd/design-core/pull/2) [`af3a0b3`](https://github.com/lapismd/design-core/commit/af3a0b3aaabd24be368acea795b150af8f4e5b89) Thanks [@stevejuma](https://github.com/stevejuma)! - Keep workspace menu close handling lifecycle-safe when an action callback destroys its owning view.
|
|
30
|
+
|
|
31
|
+
- [#4](https://github.com/lapismd/design-core/pull/4) [`d153167`](https://github.com/lapismd/design-core/commit/d15316795ce7601a483796bce23f78bfc37188ae) Thanks [@stevejuma](https://github.com/stevejuma)! - Allow App Shell body content and body sidebar regions to configure scroll, hover, or always-on scrollbar visibility independently.
|
|
32
|
+
|
|
33
|
+
- [#4](https://github.com/lapismd/design-core/pull/4) [`31c7a2c`](https://github.com/lapismd/design-core/commit/31c7a2cb438213d75a5ef3193e957cd7c35dc34f) Thanks [@stevejuma](https://github.com/stevejuma)! - Inset vertical and horizontal Scroll Area thumbs by one pixel from their outer edge.
|
|
34
|
+
|
|
35
|
+
- [#4](https://github.com/lapismd/design-core/pull/4) [`24a6e98`](https://github.com/lapismd/design-core/commit/24a6e989354b9d00d2d93786e4255da088812ee9) Thanks [@stevejuma](https://github.com/stevejuma)! - Expose the canonical two-expanded-sidebars App Shell fixture, including bounded content extension points and an optional right-sidebar toggle, for downstream Storybook catalogs. Keep the focused Search Filter Bar source export compatible with strict consumers.
|
|
36
|
+
|
|
37
|
+
- [#4](https://github.com/lapismd/design-core/pull/4) [`413139d`](https://github.com/lapismd/design-core/commit/413139d1269d5f939d20c1f00de45f151372eae0) Thanks [@stevejuma](https://github.com/stevejuma)! - Keep composed Shadcn, AI, and Filter source exports compatible with strict consumers that enable exact optional properties and unchecked indexed access.
|
|
38
|
+
|
|
39
|
+
- [#4](https://github.com/lapismd/design-core/pull/4) [`61fa863`](https://github.com/lapismd/design-core/commit/61fa86315a840717c39f0a0701d8cb208a187cb2) Thanks [@stevejuma](https://github.com/stevejuma)! - Keep the public App Shell source compatible with consumers that enable exact optional-property semantics.
|
|
40
|
+
|
|
41
|
+
## 0.1.1
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- [`d1dc4a8`](https://github.com/lapismd/design-core/commit/d1dc4a8fb13eec9b59075712f964a89cee18a1a8) Thanks [@stevejuma](https://github.com/stevejuma)! - Allow custom settings pages to contribute dynamic search entries and reveal the selected row before Design Core scrolls to and highlights it.
|
|
46
|
+
|
|
3
47
|
## 0.1.0
|
|
4
48
|
|
|
5
49
|
### Initial public release
|
package/LICENSE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
Apache-2.0
|
|
2
2
|
|
|
3
|
-
This project is licensed under the
|
|
4
|
-
See <https://www.
|
|
3
|
+
This project is licensed under the Apache License 2.0.
|
|
4
|
+
See <https://www.apache.org/licenses/LICENSE-2.0>.
|
package/README.md
CHANGED
|
@@ -224,6 +224,26 @@ pnpm spec:search -- "tokens"
|
|
|
224
224
|
pnpm spec:check
|
|
225
225
|
```
|
|
226
226
|
|
|
227
|
+
### CI and local parity
|
|
228
|
+
|
|
229
|
+
`pnpm checks` runs the nonvisual governance, quality, unit, Storybook, pointer,
|
|
230
|
+
and AI browser lanes through Turbo. Governance, quality, and unit work executes
|
|
231
|
+
concurrently with half the available processors, capped at four. Resource-heavy
|
|
232
|
+
Storybook and browser suites run one at a time locally so catalog startup and
|
|
233
|
+
interaction readiness remain deterministic; set `TURBO_CONCURRENCY` to a
|
|
234
|
+
positive number or percentage to override the general task bound.
|
|
235
|
+
|
|
236
|
+
Local task output is cached under `.turbo/`. The same tasks use the signed
|
|
237
|
+
organization cache in CI and fail open to normal execution when it is
|
|
238
|
+
unavailable. To use the remote cache locally, copy `.env.example` to the ignored
|
|
239
|
+
root `.env` and provide `TURBO_TOKEN` and
|
|
240
|
+
`TURBO_REMOTE_CACHE_SIGNATURE_KEY`. Never commit those credentials.
|
|
241
|
+
|
|
242
|
+
CI fans the nine nonvisual lanes out in parallel, including separate Workspace,
|
|
243
|
+
Shell, Shadcn, and AI browser runners. It runs full and production dependency
|
|
244
|
+
audits after they pass and reports one stable `Validate` result. Visual
|
|
245
|
+
comparison remains an explicit, separate command.
|
|
246
|
+
|
|
227
247
|
## Release and validation
|
|
228
248
|
|
|
229
249
|
Common validation commands:
|
|
@@ -246,7 +266,7 @@ pnpm release:plan --registry https://registry.npmjs.org
|
|
|
246
266
|
pnpm packages:pack
|
|
247
267
|
```
|
|
248
268
|
|
|
249
|
-
|
|
269
|
+
`@lapismd/design-core@0.1.0` was manually bootstrapped from a reviewed tarball.
|
|
250
270
|
Future releases use Changesets and the repository release workflow.
|
|
251
271
|
|
|
252
272
|
## Further reading
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lapismd/design-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Shared Lapis design system, forms, shell, and workspace primitives",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/lapismd/design-core.git"
|
|
@@ -36,7 +36,6 @@
|
|
|
36
36
|
"svelte": "^5.0.0"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@lapismd/mira": "^0.0.1",
|
|
40
39
|
"@codemirror/autocomplete": "^6.18.0",
|
|
41
40
|
"@codemirror/commands": "^6.8.0",
|
|
42
41
|
"@codemirror/lang-java": "^6.0.2",
|
|
@@ -54,16 +53,19 @@
|
|
|
54
53
|
"@iconify-json/lucide": "^1.2.63",
|
|
55
54
|
"@iconify/utils": "^2.3.0",
|
|
56
55
|
"@internationalized/date": "^3.12.2",
|
|
56
|
+
"@lapismd/mira": "^0.0.1",
|
|
57
57
|
"@lezer/common": "^1.2.3",
|
|
58
58
|
"@lezer/highlight": "^1.2.3",
|
|
59
59
|
"@lezer/lr": "^1.4.2",
|
|
60
60
|
"@lucide/svelte": "^1.21.0",
|
|
61
|
+
"@tanstack/svelte-virtual": "^3.13.39",
|
|
62
|
+
"@types/luxon": "^3.4.2",
|
|
61
63
|
"bits-ui": "^2.18.1",
|
|
62
64
|
"chrono-node": "^2.10.1",
|
|
63
65
|
"clsx": "^2.1.1",
|
|
64
66
|
"codemirror-lang-mermaid": "^0.5.0",
|
|
65
67
|
"luxon": "^3.5.0",
|
|
66
|
-
"minimatch": "^10.2.
|
|
68
|
+
"minimatch": "^10.2.6",
|
|
67
69
|
"paneforge": "^1.0.2",
|
|
68
70
|
"shadcn-svelte": "^1.3.0",
|
|
69
71
|
"tailwind-merge": "^3.6.0",
|
|
@@ -90,28 +92,27 @@
|
|
|
90
92
|
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
|
91
93
|
"@tailwindcss/cli": "^4.3.3",
|
|
92
94
|
"@tailwindcss/vite": "^4.3.0",
|
|
93
|
-
"@tobilu/qmd": "2.5.3",
|
|
94
95
|
"@testing-library/jest-dom": "^7.0.0",
|
|
95
96
|
"@testing-library/react": "^16.3.2",
|
|
96
97
|
"@testing-library/user-event": "^14.6.1",
|
|
97
|
-
"@
|
|
98
|
+
"@tobilu/qmd": "2.5.3",
|
|
98
99
|
"@types/node": "^22.15.0",
|
|
99
100
|
"@types/pixelmatch": "^5.2.6",
|
|
100
101
|
"@types/pngjs": "^6.0.5",
|
|
101
102
|
"@types/react": "^19.2.17",
|
|
102
103
|
"@types/react-dom": "^19.2.3",
|
|
103
|
-
"@vitest/browser": "^4.1.
|
|
104
|
-
"@vitest/browser-playwright": "^4.1.
|
|
104
|
+
"@vitest/browser": "^4.1.11",
|
|
105
|
+
"@vitest/browser-playwright": "^4.1.11",
|
|
105
106
|
"aria-query": "5.3.2",
|
|
106
107
|
"execa": "^10.0.0",
|
|
107
108
|
"highlight.js": "^11.11.1",
|
|
108
109
|
"jsdom": "^29.1.1",
|
|
109
110
|
"magic-string": "^1.0.0",
|
|
110
|
-
"markdownlint-cli2": "^0.
|
|
111
|
+
"markdownlint-cli2": "^0.23.2",
|
|
111
112
|
"pixelmatch": "^7.2.0",
|
|
112
113
|
"playwright": "^1.52.0",
|
|
113
114
|
"pngjs": "^7.0.0",
|
|
114
|
-
"postcss": "^8.5.
|
|
115
|
+
"postcss": "^8.5.28",
|
|
115
116
|
"postcss-selector-parser": "^7.1.4",
|
|
116
117
|
"prettier": "3.3.3",
|
|
117
118
|
"prettier-plugin-svelte": "^3.3.2",
|
|
@@ -124,9 +125,10 @@
|
|
|
124
125
|
"svelte-check": "^4.6.0",
|
|
125
126
|
"tailwindcss": "^4.3.0",
|
|
126
127
|
"tsx": "^4.23.1",
|
|
128
|
+
"turbo": "^2.5.4",
|
|
127
129
|
"typescript": "^5.7.2",
|
|
128
130
|
"vite": "^6.2.2",
|
|
129
|
-
"vitest": "^4.1.
|
|
131
|
+
"vitest": "^4.1.11",
|
|
130
132
|
"zod": "^4.4.3"
|
|
131
133
|
},
|
|
132
134
|
"exports": {
|
|
@@ -174,6 +176,7 @@
|
|
|
174
176
|
"./styles.css": "./src/styles.css",
|
|
175
177
|
"./storybook.css": "./src/storybook.css",
|
|
176
178
|
"./storybook/catalog-layout": "./src/storybook/catalog-layout.ts",
|
|
179
|
+
"./storybook/app-shell-reference": "./src/storybook/app-shell-reference/index.ts",
|
|
177
180
|
"./themes/lapis.css": "./src/themes/lapis.css",
|
|
178
181
|
"./ai": "./src/shared/ai/index.ts",
|
|
179
182
|
"./ai/chat": "./src/shared/ai/chat.ts",
|
|
@@ -225,7 +228,8 @@
|
|
|
225
228
|
"./workspace/view-header": "./src/shared/workspace/view-header/index.ts",
|
|
226
229
|
"./workspace/tokens": "./src/shared/workspace/workspace.tokens.ts",
|
|
227
230
|
"./workspace/view-host": "./src/shared/workspace/view-host/index.ts",
|
|
228
|
-
"./workspace/workspace.tokens.css": "./src/shared/workspace/workspace.tokens.css"
|
|
231
|
+
"./workspace/workspace.tokens.css": "./src/shared/workspace/workspace.tokens.css",
|
|
232
|
+
"./forms/dialog": "./src/shared/forms/dialog.ts"
|
|
229
233
|
},
|
|
230
234
|
"scripts": {
|
|
231
235
|
"storybook": "WATCHPACK_POLLING=250 node scripts/with-storybook-env.mjs node scripts/storybook-run.mjs",
|
|
@@ -233,9 +237,11 @@
|
|
|
233
237
|
"storybook:stop": "node scripts/with-storybook-env.mjs bash scripts/storybook-stop.sh",
|
|
234
238
|
"storybook:restart": "node scripts/with-storybook-env.mjs bash scripts/storybook-restart.sh",
|
|
235
239
|
"storybook:check": "pnpm test:storybook && pnpm test:workspace:pointer && pnpm test:shell:pointer && pnpm test:shadcn:pointer && pnpm build-storybook && pnpm workspace:visual:audit",
|
|
236
|
-
"build-storybook": "node
|
|
240
|
+
"build-storybook": "node --env-file-if-exists=.env scripts/run-turbo.mjs build:storybook",
|
|
241
|
+
"build:storybook": "node -e \"require('node:fs').mkdirSync('.visual-delta/cache',{recursive:true})\" && node --max-old-space-size=6144 ./node_modules/storybook/dist/bin/dispatcher.js build --stats-json .visual-delta/cache",
|
|
237
242
|
"changeset": "changeset",
|
|
238
243
|
"test:unit": "vitest run --project unit",
|
|
244
|
+
"test:turbo": "node --test scripts/concurrency.test.mjs scripts/turbo-cache-report.test.mjs",
|
|
239
245
|
"test:storybook": "vitest run --project storybook",
|
|
240
246
|
"test:storybook:watch": "vitest --project storybook",
|
|
241
247
|
"spec:build": "spec-validator build",
|
|
@@ -277,11 +283,24 @@
|
|
|
277
283
|
"ui:visual:tag": "tsx scripts/ui-generator/cli.ts visual:tag",
|
|
278
284
|
"test-unit": "pnpm test:unit",
|
|
279
285
|
"test-storybook": "pnpm test:storybook",
|
|
280
|
-
"check": "pnpm spec:validate &&
|
|
286
|
+
"check": "pnpm spec:validate && pnpm check:types",
|
|
287
|
+
"check:types": "svelte-check --tsconfig ./tsconfig.json --fail-on-warnings && pnpm check:shell-consumer && pnpm check:filter-consumer && pnpm check:source-consumer",
|
|
288
|
+
"check:filter-consumer": "svelte-check --tsconfig ./tsconfig.filter-consumer.json --fail-on-warnings",
|
|
289
|
+
"check:shell-consumer": "svelte-check --tsconfig ./tsconfig.shell-consumer.json --fail-on-warnings",
|
|
290
|
+
"check:source-consumer": "svelte-check --tsconfig ./tsconfig.source-consumer.json --fail-on-warnings",
|
|
281
291
|
"fmt": "prettier . --write",
|
|
282
292
|
"fmt:check": "prettier . --check",
|
|
283
293
|
"check:no-tailwind": "tsx scripts/check-no-tailwind-utilities.ts",
|
|
284
|
-
"
|
|
294
|
+
"ci:governance": "pnpm spec:check",
|
|
295
|
+
"ci:quality": "pnpm fmt:check && pnpm check:types && pnpm check:no-tailwind",
|
|
296
|
+
"ci:unit": "pnpm test:unit && pnpm test:turbo",
|
|
297
|
+
"ci:storybook-static": "pnpm workspace:visual:audit -- --index=storybook-static/index.json",
|
|
298
|
+
"ci:storybook-interaction": "pnpm test:storybook",
|
|
299
|
+
"ci:browser-workspace": "pnpm test:workspace:pointer",
|
|
300
|
+
"ci:browser-shell": "pnpm test:shell:pointer",
|
|
301
|
+
"ci:browser-shadcn": "pnpm test:shadcn:pointer",
|
|
302
|
+
"ci:browser-ai": "pnpm test:ai-chat-browser",
|
|
303
|
+
"checks:nonvisual": "node --env-file-if-exists=.env scripts/run-turbo.mjs ci:governance ci:quality ci:unit --summarize && node --env-file-if-exists=.env scripts/run-turbo.mjs ci:storybook-static --summarize && node --env-file-if-exists=.env scripts/run-turbo.mjs ci:storybook-interaction --summarize && node --env-file-if-exists=.env scripts/run-turbo.mjs ci:browser-workspace --summarize && node --env-file-if-exists=.env scripts/run-turbo.mjs ci:browser-shell --summarize && node --env-file-if-exists=.env scripts/run-turbo.mjs ci:browser-ai --summarize && node --env-file-if-exists=.env scripts/run-turbo.mjs ci:browser-shadcn --summarize",
|
|
285
304
|
"checks:release": "pnpm spec:check && pnpm check && pnpm check:no-tailwind && pnpm test:unit && pnpm build-storybook && pnpm workspace:visual:audit",
|
|
286
305
|
"checks": "pnpm checks:nonvisual",
|
|
287
306
|
"checks:visual": "pnpm checks:nonvisual && pnpm test:visual",
|
|
@@ -107,15 +107,15 @@ pages.
|
|
|
107
107
|
|
|
108
108
|
### Token layers
|
|
109
109
|
|
|
110
|
-
| Layer | Prefix | Defaults
|
|
111
|
-
| ------------------- | ------------------------------ |
|
|
112
|
-
| Theme | `--background`, `--primary`, … | `src/theme.css`
|
|
113
|
-
| Shadcn family | `--ui-<family>-*` | `<family>.tokens.css`
|
|
114
|
-
| Forms | `--ui-form-*` | `src/shared/forms/form.tokens.css`
|
|
115
|
-
| Filter and AI | `--ui-*` / `--ui-ai-*` | colocated CSS and token maps
|
|
116
|
-
| Diff | `--ui-diff-*` | `src/shared/diff/diff.tokens.css`
|
|
117
|
-
| Structural shell | `--ui-shell-*` | `src/shared/shell/shell.tokens.css`
|
|
118
|
-
| Workspace framework | `--ui-workspace-*` | `src/shared/workspace/workspace.tokens.css`
|
|
110
|
+
| Layer | Prefix | Defaults |
|
|
111
|
+
| ------------------- | ------------------------------ | ------------------------------------------------- |
|
|
112
|
+
| Theme | `--background`, `--primary`, … | `src/theme.css` |
|
|
113
|
+
| Shadcn family | `--ui-<family>-*` | `<family>.tokens.css` |
|
|
114
|
+
| Forms | `--ui-form-*` | `src/shared/forms/form.tokens.css` |
|
|
115
|
+
| Filter and AI | `--ui-*` / `--ui-ai-*` | colocated CSS and token maps |
|
|
116
|
+
| Diff | `--ui-diff-*` | `src/shared/diff/diff.tokens.css` |
|
|
117
|
+
| Structural shell | `--ui-shell-*` | `src/shared/shell/shell.tokens.css` |
|
|
118
|
+
| Workspace framework | `--ui-workspace-*` | `src/shared/workspace/workspace.tokens.css` |
|
|
119
119
|
| Desktop drag | `data-desktop-drag-region` | `src/shared/workspace/workspace-desktop-drag.css` |
|
|
120
120
|
|
|
121
121
|
Set public tokens on `:root` or an appropriate shared ancestor such as
|
|
@@ -186,3 +186,5 @@ refuses leftover utilities after native-CSS conversion.
|
|
|
186
186
|
4. Stamp `data-ui-component` and `data-ui-part`.
|
|
187
187
|
5. Document the tokens the component reads.
|
|
188
188
|
6. Run `pnpm check:no-tailwind`, focused story checks, and the repository gate.
|
|
189
|
+
|
|
190
|
+
Dialog recipes consume runtime container and text tokens explicitly defined in the theme so packaged consumers retain geometry without generating Tailwind utilities.
|
package/src/shared/ai/chat.css
CHANGED
|
@@ -1031,7 +1031,8 @@
|
|
|
1031
1031
|
|
|
1032
1032
|
[data-ui-component="ai-chat-composer-drawer"]
|
|
1033
1033
|
[data-ai-chat-part="drawer-content"]
|
|
1034
|
-
[data-ui-part="attachment-remove"]
|
|
1034
|
+
[data-ui-part="attachment-remove"]
|
|
1035
|
+
svg {
|
|
1035
1036
|
width: 0.75rem;
|
|
1036
1037
|
height: 0.75rem;
|
|
1037
1038
|
}
|
|
@@ -1549,3 +1550,26 @@
|
|
|
1549
1550
|
animation: none;
|
|
1550
1551
|
}
|
|
1551
1552
|
}
|
|
1553
|
+
|
|
1554
|
+
[data-ui-component="ai-chat-message-list"] [data-ui-part="virtual-content"] {
|
|
1555
|
+
position: relative;
|
|
1556
|
+
flex: 0 0 auto;
|
|
1557
|
+
width: 100%;
|
|
1558
|
+
overflow-anchor: none;
|
|
1559
|
+
}
|
|
1560
|
+
[data-ui-component="ai-chat-message-list"] [data-ui-part="virtual-row"] {
|
|
1561
|
+
position: absolute;
|
|
1562
|
+
top: 0;
|
|
1563
|
+
left: 0;
|
|
1564
|
+
width: 100%;
|
|
1565
|
+
padding-bottom: var(--ui-ai-chat-balanced-gap);
|
|
1566
|
+
overflow-anchor: none;
|
|
1567
|
+
}
|
|
1568
|
+
[data-ui-component="ai-chat-message-list"][data-density="compact"]
|
|
1569
|
+
[data-ui-part="virtual-row"] {
|
|
1570
|
+
padding-bottom: var(--ui-ai-chat-compact-gap);
|
|
1571
|
+
}
|
|
1572
|
+
[data-ui-component="ai-chat-message-list"][data-density="spacious"]
|
|
1573
|
+
[data-ui-part="virtual-row"] {
|
|
1574
|
+
padding-bottom: var(--ui-ai-chat-spacious-gap);
|
|
1575
|
+
}
|
package/src/shared/ai/chat.ts
CHANGED
|
@@ -12,6 +12,15 @@ export { default as SendButton } from "./send-button/SendButton.svelte";
|
|
|
12
12
|
export { default as ComposerToken } from "./composer-token/ComposerToken.svelte";
|
|
13
13
|
export { default as TokenizedText } from "./tokenized-text/TokenizedText.svelte";
|
|
14
14
|
export { default as ToolCalls } from "./tool-calls/ToolCalls.svelte";
|
|
15
|
+
export { default as ToolCallDetail } from "./tool-call-detail/ToolCallDetail.svelte";
|
|
16
|
+
export {
|
|
17
|
+
isOneLineToolAlert,
|
|
18
|
+
presentToolPayload,
|
|
19
|
+
toolCallTarget,
|
|
20
|
+
type PresentedToolPayload,
|
|
21
|
+
type ToolPayloadHint,
|
|
22
|
+
type ToolPayloadLanguage,
|
|
23
|
+
} from "./tool-call-detail/tool-call-detail.js";
|
|
15
24
|
export { default as DictationButton } from "./dictation-button/DictationButton.svelte";
|
|
16
25
|
|
|
17
26
|
export {
|
|
@@ -19,6 +28,7 @@ export {
|
|
|
19
28
|
type ScrollBehavior,
|
|
20
29
|
type ScrollToBottomOptions,
|
|
21
30
|
type StreamScrollController,
|
|
31
|
+
type PositionedStreamScrollController,
|
|
22
32
|
type StreamScrollOptions,
|
|
23
33
|
} from "./stream-scroll.svelte.js";
|
|
24
34
|
export {
|
|
@@ -68,3 +78,5 @@ export type {
|
|
|
68
78
|
ToolCallStatus,
|
|
69
79
|
} from "./types.js";
|
|
70
80
|
export type { ComposerToken as ComposerTokenValue } from "./types.js";
|
|
81
|
+
|
|
82
|
+
export type { MessageListPosition } from "./message-list/position.js";
|
|
@@ -331,9 +331,10 @@
|
|
|
331
331
|
Math.max(1, searchState.items.length);
|
|
332
332
|
return;
|
|
333
333
|
}
|
|
334
|
-
|
|
334
|
+
const highlightedItem = searchState.items[highlightedIndex];
|
|
335
|
+
if (event.key === "Enter" && highlightedItem) {
|
|
335
336
|
event.preventDefault();
|
|
336
|
-
insertTriggerSelection(
|
|
337
|
+
insertTriggerSelection(highlightedItem);
|
|
337
338
|
return;
|
|
338
339
|
}
|
|
339
340
|
if (event.key === "Escape") {
|
|
@@ -12,6 +12,8 @@ export type LayoutContextValue = {
|
|
|
12
12
|
getScrollContainer: () => HTMLElement | null;
|
|
13
13
|
setScrollContainer: (element: HTMLElement | null) => void;
|
|
14
14
|
setContent: (element: HTMLElement | null) => void;
|
|
15
|
+
/** A virtual list owns row resize anchoring; the layout still owns scroll writes. */
|
|
16
|
+
setVirtualized?: (active: boolean) => void;
|
|
15
17
|
streamScroll: StreamScrollController;
|
|
16
18
|
newMessages: NewMessagesController;
|
|
17
19
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import SparklesIcon from "@lucide/svelte/icons/sparkles";
|
|
3
|
-
import type
|
|
3
|
+
import { untrack, type Snippet } from "svelte";
|
|
4
4
|
import type { HTMLAttributes } from "svelte/elements";
|
|
5
5
|
import * as Empty from "@lapismd/design-core/shadcn/empty";
|
|
6
6
|
import { ScrollArea } from "@lapismd/design-core/shadcn/scroll-area";
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
scrollRef = $bindable(null),
|
|
17
17
|
density = "balanced",
|
|
18
18
|
isEmpty = false,
|
|
19
|
+
scrollMode = "stream",
|
|
20
|
+
conversationKey,
|
|
21
|
+
hasNewMessages: controlledNewMessages,
|
|
22
|
+
hasNewer = false,
|
|
23
|
+
onLoadLatest,
|
|
24
|
+
onViewportChange,
|
|
19
25
|
emptyState,
|
|
20
26
|
scrollButton,
|
|
21
27
|
composer,
|
|
@@ -27,6 +33,13 @@
|
|
|
27
33
|
scrollRef?: HTMLElement | null;
|
|
28
34
|
density?: Density;
|
|
29
35
|
isEmpty?: boolean;
|
|
36
|
+
/** Keep streaming scroll behavior by default; opt in to anchored cached-history navigation. */
|
|
37
|
+
scrollMode?: "stream" | "history";
|
|
38
|
+
conversationKey?: string;
|
|
39
|
+
hasNewMessages?: boolean;
|
|
40
|
+
hasNewer?: boolean;
|
|
41
|
+
onLoadLatest?: () => Promise<void>;
|
|
42
|
+
onViewportChange?: (state: { atLatest: boolean; active: boolean }) => void;
|
|
30
43
|
emptyState?: Snippet;
|
|
31
44
|
scrollButton?: Snippet<
|
|
32
45
|
[
|
|
@@ -43,12 +56,20 @@
|
|
|
43
56
|
|
|
44
57
|
let messageAreaRef = $state<HTMLElement | null>(null);
|
|
45
58
|
let contentRef = $state<HTMLElement | null>(null);
|
|
46
|
-
|
|
59
|
+
let virtualized = false;
|
|
60
|
+
const streamScroll = createStreamScroll({
|
|
61
|
+
anchorOnResize: () => scrollMode === "history",
|
|
62
|
+
});
|
|
47
63
|
const newMessages = createNewMessages({
|
|
64
|
+
deferResize: () => scrollMode === "history",
|
|
48
65
|
isLocked: () => streamScroll.isLocked,
|
|
49
66
|
onResize: () => {
|
|
50
|
-
|
|
51
|
-
|
|
67
|
+
if (scrollMode === "history")
|
|
68
|
+
streamScroll.contentResized({ restoreAnchor: !virtualized });
|
|
69
|
+
else {
|
|
70
|
+
streamScroll.scrollIfLocked();
|
|
71
|
+
streamScroll.update();
|
|
72
|
+
}
|
|
52
73
|
},
|
|
53
74
|
});
|
|
54
75
|
|
|
@@ -57,10 +78,89 @@
|
|
|
57
78
|
newMessages.attach(element);
|
|
58
79
|
}
|
|
59
80
|
|
|
81
|
+
let pendingJump = false;
|
|
82
|
+
let jumpVersion = 0;
|
|
83
|
+
let priorConversationKey: string | undefined;
|
|
84
|
+
let conversationInitialized = false;
|
|
85
|
+
let jumpError = $state<string | undefined>();
|
|
86
|
+
let documentActive = $state(true);
|
|
87
|
+
const unread = $derived(controlledNewMessages ?? newMessages.hasNewMessages);
|
|
88
|
+
const showNewMessages = $derived(
|
|
89
|
+
unread && (!streamScroll.isLocked || hasNewer || !documentActive),
|
|
90
|
+
);
|
|
91
|
+
const showScrollButton = $derived(
|
|
92
|
+
streamScroll.isScrolledUp || showNewMessages || hasNewer,
|
|
93
|
+
);
|
|
60
94
|
function scrollToBottom(): void {
|
|
61
|
-
|
|
62
|
-
|
|
95
|
+
if (pendingJump) return;
|
|
96
|
+
if (scrollMode === "stream" && !onLoadLatest) {
|
|
97
|
+
newMessages.dismiss();
|
|
98
|
+
streamScroll.scrollToBottom();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const key = conversationKey;
|
|
102
|
+
const version = ++jumpVersion;
|
|
103
|
+
const revision = streamScroll.positionRevision;
|
|
104
|
+
pendingJump = true;
|
|
105
|
+
jumpError = undefined;
|
|
106
|
+
void (async () => {
|
|
107
|
+
try {
|
|
108
|
+
await onLoadLatest?.();
|
|
109
|
+
if (
|
|
110
|
+
key === conversationKey &&
|
|
111
|
+
version === jumpVersion &&
|
|
112
|
+
revision === streamScroll.positionRevision
|
|
113
|
+
)
|
|
114
|
+
streamScroll.scrollToBottom({
|
|
115
|
+
behavior: scrollMode === "history" ? "instant" : "spring",
|
|
116
|
+
});
|
|
117
|
+
} catch (cause) {
|
|
118
|
+
if (key === conversationKey && version === jumpVersion)
|
|
119
|
+
jumpError =
|
|
120
|
+
cause instanceof Error
|
|
121
|
+
? cause.message
|
|
122
|
+
: "Could not load latest messages";
|
|
123
|
+
} finally {
|
|
124
|
+
if (version === jumpVersion) pendingJump = false;
|
|
125
|
+
}
|
|
126
|
+
})();
|
|
63
127
|
}
|
|
128
|
+
$effect(() => {
|
|
129
|
+
const key = conversationKey;
|
|
130
|
+
untrack(() => {
|
|
131
|
+
if (conversationInitialized && key === priorConversationKey) return;
|
|
132
|
+
conversationInitialized = true;
|
|
133
|
+
priorConversationKey = key;
|
|
134
|
+
jumpVersion++;
|
|
135
|
+
pendingJump = false;
|
|
136
|
+
if (key === undefined) return;
|
|
137
|
+
newMessages.attach(contentRef ?? messageAreaRef);
|
|
138
|
+
streamScroll.attach(null);
|
|
139
|
+
streamScroll.attach(scrollRef);
|
|
140
|
+
jumpError = undefined;
|
|
141
|
+
});
|
|
142
|
+
return () => {
|
|
143
|
+
void key;
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
$effect(() => {
|
|
147
|
+
if (streamScroll.isLocked && !hasNewer && documentActive)
|
|
148
|
+
newMessages.dismiss();
|
|
149
|
+
const observation = {
|
|
150
|
+
atLatest: streamScroll.isLocked && !hasNewer,
|
|
151
|
+
active: documentActive,
|
|
152
|
+
};
|
|
153
|
+
const notify = onViewportChange;
|
|
154
|
+
untrack(() => notify?.(observation));
|
|
155
|
+
});
|
|
156
|
+
$effect(() => {
|
|
157
|
+
const update = () => {
|
|
158
|
+
documentActive = document.visibilityState !== "hidden";
|
|
159
|
+
};
|
|
160
|
+
update();
|
|
161
|
+
document.addEventListener("visibilitychange", update);
|
|
162
|
+
return () => document.removeEventListener("visibilitychange", update);
|
|
163
|
+
});
|
|
64
164
|
|
|
65
165
|
setLayoutContext({
|
|
66
166
|
getScrollContainer: () => scrollRef,
|
|
@@ -69,6 +169,9 @@
|
|
|
69
169
|
streamScroll.attach(element);
|
|
70
170
|
},
|
|
71
171
|
setContent,
|
|
172
|
+
setVirtualized(active) {
|
|
173
|
+
virtualized = active;
|
|
174
|
+
},
|
|
72
175
|
streamScroll,
|
|
73
176
|
newMessages,
|
|
74
177
|
});
|
|
@@ -118,16 +221,19 @@
|
|
|
118
221
|
{/if}
|
|
119
222
|
</div>
|
|
120
223
|
</ScrollArea>
|
|
224
|
+
{#if jumpError}<p role="alert" data-ui-part="history-error">
|
|
225
|
+
{jumpError}
|
|
226
|
+
</p>{/if}
|
|
121
227
|
{#if scrollButton}
|
|
122
228
|
{@render scrollButton({
|
|
123
|
-
isVisible:
|
|
124
|
-
hasNewMessages:
|
|
229
|
+
isVisible: showScrollButton,
|
|
230
|
+
hasNewMessages: showNewMessages,
|
|
125
231
|
scrollToBottom,
|
|
126
232
|
})}
|
|
127
233
|
{:else}
|
|
128
234
|
<LayoutScrollButton
|
|
129
|
-
isVisible={
|
|
130
|
-
hasNewMessages={
|
|
235
|
+
isVisible={showScrollButton}
|
|
236
|
+
hasNewMessages={showNewMessages}
|
|
131
237
|
onClick={scrollToBottom}
|
|
132
238
|
/>
|
|
133
239
|
{/if}
|