@ketvietlab/design-system 0.1.16 → 0.1.17

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 (94) hide show
  1. package/README.md +29 -0
  2. package/dist/catalogue/catalogue.css +8 -0
  3. package/dist/catalogue/index.js +1 -1
  4. package/dist/catalogue/inventory-policy.json +21 -0
  5. package/dist/catalogue/inventory.generated.js +1 -1
  6. package/dist/catalogue/inventory.generated.js.map +1 -1
  7. package/dist/catalogue/inventory.generated.json +646 -84
  8. package/dist/catalogue/registry.d.ts.map +1 -1
  9. package/dist/catalogue/registry.js +6 -0
  10. package/dist/catalogue/registry.js.map +1 -1
  11. package/dist/catalogue/specimens.d.ts.map +1 -1
  12. package/dist/catalogue/specimens.js +113 -8
  13. package/dist/catalogue/specimens.js.map +1 -1
  14. package/dist/contract/index.d.ts.map +1 -1
  15. package/dist/contract/index.js +6 -0
  16. package/dist/contract/index.js.map +1 -1
  17. package/dist/data-display/bar-chart/index.d.ts +61 -0
  18. package/dist/data-display/bar-chart/index.d.ts.map +1 -0
  19. package/dist/data-display/bar-chart/index.js +64 -0
  20. package/dist/data-display/bar-chart/index.js.map +1 -0
  21. package/dist/data-display/bar-chart/styles.css +191 -0
  22. package/dist/data-display/matrix/index.d.ts +36 -0
  23. package/dist/data-display/matrix/index.d.ts.map +1 -0
  24. package/dist/data-display/matrix/index.js +28 -0
  25. package/dist/data-display/matrix/index.js.map +1 -0
  26. package/dist/data-display/matrix/styles.css +148 -0
  27. package/dist/data-operations/timeframe-filter/index.d.ts +34 -0
  28. package/dist/data-operations/timeframe-filter/index.d.ts.map +1 -0
  29. package/dist/data-operations/timeframe-filter/index.js +30 -0
  30. package/dist/data-operations/timeframe-filter/index.js.map +1 -0
  31. package/dist/data-operations/timeframe-filter/styles.css +109 -0
  32. package/dist/foundations/tokens.css +10 -0
  33. package/dist/index.d.ts +11 -3
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +4 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/interactions/menu/index.d.ts +17 -2
  38. package/dist/interactions/menu/index.d.ts.map +1 -1
  39. package/dist/interactions/menu/index.js +21 -5
  40. package/dist/interactions/menu/index.js.map +1 -1
  41. package/dist/interactions/menu/styles.css +36 -0
  42. package/dist/layouts/app-navigation/styles.css +8 -0
  43. package/dist/layouts/layout/index.d.ts +43 -3
  44. package/dist/layouts/layout/index.d.ts.map +1 -1
  45. package/dist/layouts/layout/index.js +28 -4
  46. package/dist/layouts/layout/index.js.map +1 -1
  47. package/dist/layouts/layout/styles.css +182 -4
  48. package/dist/layouts/page-identity/index.d.ts +19 -0
  49. package/dist/layouts/page-identity/index.d.ts.map +1 -0
  50. package/dist/layouts/page-identity/index.js +6 -0
  51. package/dist/layouts/page-identity/index.js.map +1 -0
  52. package/dist/layouts/shell/index.d.ts +7 -11
  53. package/dist/layouts/shell/index.d.ts.map +1 -1
  54. package/dist/layouts/shell/index.js +12 -2
  55. package/dist/layouts/shell/index.js.map +1 -1
  56. package/dist/layouts/shell/styles.css +16 -31
  57. package/dist/patterns/data-table/index.d.ts.map +1 -1
  58. package/dist/patterns/data-table/index.js +1 -1
  59. package/dist/patterns/data-table/index.js.map +1 -1
  60. package/dist/patterns/data-table/styles.css +124 -43
  61. package/dist/patterns/list-chrome/index.d.ts +2 -2
  62. package/dist/patterns/list-chrome/index.d.ts.map +1 -1
  63. package/dist/patterns/list-chrome/index.js +4 -3
  64. package/dist/patterns/list-chrome/index.js.map +1 -1
  65. package/dist/patterns/list-chrome/styles.css +122 -40
  66. package/dist/patterns/list-page/styles.css +5 -1
  67. package/dist/patterns/modal-sheet/styles.css +1 -1
  68. package/dist/patterns/page-shell/index.d.ts +2 -23
  69. package/dist/patterns/page-shell/index.d.ts.map +1 -1
  70. package/dist/patterns/page-shell/index.js +1 -10
  71. package/dist/patterns/page-shell/index.js.map +1 -1
  72. package/dist/patterns/page-shell/styles.css +131 -0
  73. package/dist/patterns/patterns.css +1 -0
  74. package/dist/primitives/feedback/index.d.ts.map +1 -1
  75. package/dist/primitives/feedback/index.js +1 -1
  76. package/dist/primitives/feedback/index.js.map +1 -1
  77. package/dist/primitives/feedback/styles.css +13 -11
  78. package/dist/primitives/navigation/index.d.ts +11 -5
  79. package/dist/primitives/navigation/index.d.ts.map +1 -1
  80. package/dist/primitives/navigation/index.js +17 -2
  81. package/dist/primitives/navigation/index.js.map +1 -1
  82. package/dist/primitives/navigation/styles.css +101 -13
  83. package/dist/primitives/status/index.d.ts.map +1 -1
  84. package/dist/primitives/status/index.js +2 -2
  85. package/dist/primitives/status/index.js.map +1 -1
  86. package/dist/primitives/status/styles.css +8 -8
  87. package/dist/record/display/index.js +1 -1
  88. package/dist/record/display/index.js.map +1 -1
  89. package/dist/record/display/styles.css +2 -2
  90. package/dist/runtime/index.d.ts.map +1 -1
  91. package/dist/runtime/index.js +99 -4
  92. package/dist/runtime/index.js.map +1 -1
  93. package/dist/styles.css +2 -50
  94. package/package.json +2 -2
package/README.md CHANGED
@@ -41,6 +41,31 @@ transparent scrolling viewport inside; never wrap it in another `Surface`.
41
41
  The title is retained in its empty state, with optional `emptyActions` for recovery.
42
42
  Omitting `title` preserves the existing unheaded form surface or standalone table.
43
43
 
44
+ ### Collections open records in a modal
45
+
46
+ A row of a `DataTable` (or `ResourceList`, `DataGrid`) and a `KanbanCard` always open
47
+ their record in a `ModalSheet` on top of the collection. They never navigate to a
48
+ separate record page. The reader keeps the collection's filters, scroll position,
49
+ selection and board column while working on one record, and closing the modal
50
+ returns them exactly where they were.
51
+
52
+ - `rowHref` and `KanbanCard href` point at the modal trigger for that record, not at
53
+ a record route. Create actions on the same collection follow the same rule.
54
+ - The modal is a client-side island. It owns open and close, focus trapping and
55
+ restoration, Escape and backdrop closing, background inertness, tabs inside the
56
+ record, unsaved-change prompts and completion feedback. Opening, switching tabs
57
+ and closing do not reload the page or rebuild the collection on the server.
58
+ - Modal state is not a separate page state. A deep link may ask the island to open a
59
+ record after hydration, but the server always renders the collection with a closed
60
+ modal host, so the server and first client render stay identical.
61
+ - Size follows content: a short record uses the default size, and only long content
62
+ such as a multi-tab record uses the large size with an internal scroll region.
63
+ - A child action of the record (reassign, postpone, confirm) opens inside the same
64
+ island as a nested step, not as another page.
65
+ - `RecordPage` remains for records reached directly rather than from a collection,
66
+ such as a shared link or a record without a parent list. It is never the target of
67
+ a collection row or card.
68
+
44
69
  The app structure is demonstrated with `AppNavigation` and four practical layouts inside `AppShell`:
45
70
  collection (`ListPage`), record (`RecordPage`), flow workspace (`WorkspacePage`
46
71
  with `layout="flow"`), and canvas workspace (`WorkspacePage` with
@@ -57,6 +82,10 @@ Only leaf links expose the active state. Top-level branches form one accordion a
57
82
  the complete sidebar, and the interaction adapter keeps the open branch from being
58
83
  collapsed without choosing another branch. Use `expanded` when a branch should start
59
84
  open without an active descendant.
85
+ Top-level navigation rows use the shared dense metrics: a 30px row, 13px label,
86
+ 10px content gap and an 18px leading icon. Icon size belongs to `AppNavigation`, so
87
+ application shells and catalogue demos render the same geometry without local icon
88
+ overrides.
60
89
  The optional interaction adapter adds mobile dialog semantics, Escape/backdrop/link
61
90
  closing, focus trapping and restoration, background inertness, and scroll locking.
62
91
 
@@ -374,6 +374,14 @@
374
374
  overflow: hidden;
375
375
  }
376
376
 
377
+ /* Overlay specimens must demonstrate the real layer instead of clipping it
378
+ to the documentation card. The normal clipped border returns when closed. */
379
+ :where([data-kv-design-system]) [data-ui="catalogue-specimen"]:has([data-ui="menu"][open]) {
380
+ position: relative;
381
+ z-index: var(--kv-layer-menu);
382
+ overflow: visible;
383
+ }
384
+
377
385
  :where([data-kv-design-system]) [data-ui="catalogue-specimen-head"] {
378
386
  display: flex;
379
387
  align-items: start;
@@ -44,7 +44,7 @@ export const CATALOGUE_HOOKS = [
44
44
  export const CatalogueHead = () => html `<meta name="description" content="Két Việt public component documentation"><link rel="stylesheet" href="/design-system/catalogue/styles.css"><script type="module" src="/design-system/runtime/auto.js"></script>`;
45
45
  const registrationsFor = (groupId) => componentRegistry.filter((registration) => registration.groupId === groupId);
46
46
  const pathWithPreferences = (path, theme, density) => `${path}?theme=${theme}&density=${density}`;
47
- const CatalogueRail = (props) => (_jsxs("aside", { "data-ui": "catalogue-rail", children: [_jsxs("a", { "data-ui": "catalogue-brand", href: pathWithPreferences('/', props.theme, props.density), children: [_jsx("span", { "aria-hidden": "true", children: "K" }), _jsx("strong", { children: "K\u00E9t Vi\u1EC7t" })] }), _jsx("p", { "data-ui": "catalogue-kicker", children: "Design system \u00B7 0.1.16" }), _jsxs("nav", { "data-ui": "catalogue-nav", "aria-label": "Design system documentation", children: [_jsx("span", { "data-ui": "catalogue-nav-section", children: "Get started" }), _jsx("a", { "data-ui": "catalogue-nav-group", href: pathWithPreferences('/', props.theme, props.density), "aria-current": props.active === 'overview' ? 'page' : null, children: _jsx("span", { children: "Overview" }) }), _jsxs("a", { "data-ui": "catalogue-nav-group", href: pathWithPreferences('/components', props.theme, props.density), "aria-current": props.active === 'components' ? 'page' : null, children: [_jsx("span", { children: "Components" }), _jsx("span", { "data-ui": "catalogue-nav-count", children: String(componentRegistry.length) })] }), _jsx("a", { "data-ui": "catalogue-nav-group", href: `/demo?theme=${props.theme}`, children: _jsx("span", { children: "Application demo" }) }), _jsx("a", { "data-ui": "catalogue-nav-group", href: `/demo2?theme=${props.theme}`, children: _jsx("span", { children: "Application submenu demo" }) }), _jsx("span", { "data-ui": "catalogue-nav-section", children: "Component groups" }), each(componentGroups, (group) => group.id, (group) => (_jsxs("a", { "data-ui": "catalogue-nav-group", href: pathWithPreferences(`/components/${group.id}`, props.theme, props.density), "aria-current": props.active === group.id ? 'page' : null, children: [_jsx("span", { children: group.name }), _jsx("span", { "data-ui": "catalogue-nav-count", children: String(registrationsFor(group.id).length) })] }))), _jsx("span", { "data-ui": "catalogue-nav-section", children: "Reference" }), _jsxs("a", { "data-ui": "catalogue-nav-group", href: "/surfaces?kind=record&theme=light", children: [_jsx("span", { children: "Page patterns" }), _jsx("span", { "data-ui": "catalogue-nav-count", children: "3" })] }), _jsx("a", { "data-ui": "catalogue-nav-group", href: "/inventory", children: _jsx("span", { children: "Inventory" }) })] })] }));
47
+ const CatalogueRail = (props) => (_jsxs("aside", { "data-ui": "catalogue-rail", children: [_jsxs("a", { "data-ui": "catalogue-brand", href: pathWithPreferences('/', props.theme, props.density), children: [_jsx("span", { "aria-hidden": "true", children: "K" }), _jsx("strong", { children: "K\u00E9t Vi\u1EC7t" })] }), _jsx("p", { "data-ui": "catalogue-kicker", children: "Design system \u00B7 0.1.17" }), _jsxs("nav", { "data-ui": "catalogue-nav", "aria-label": "Design system documentation", children: [_jsx("span", { "data-ui": "catalogue-nav-section", children: "Get started" }), _jsx("a", { "data-ui": "catalogue-nav-group", href: pathWithPreferences('/', props.theme, props.density), "aria-current": props.active === 'overview' ? 'page' : null, children: _jsx("span", { children: "Overview" }) }), _jsxs("a", { "data-ui": "catalogue-nav-group", href: pathWithPreferences('/components', props.theme, props.density), "aria-current": props.active === 'components' ? 'page' : null, children: [_jsx("span", { children: "Components" }), _jsx("span", { "data-ui": "catalogue-nav-count", children: String(componentRegistry.length) })] }), _jsx("a", { "data-ui": "catalogue-nav-group", href: `/demo?theme=${props.theme}`, children: _jsx("span", { children: "Application demo" }) }), _jsx("a", { "data-ui": "catalogue-nav-group", href: `/demo2?theme=${props.theme}`, children: _jsx("span", { children: "Application submenu demo" }) }), _jsx("span", { "data-ui": "catalogue-nav-section", children: "Component groups" }), each(componentGroups, (group) => group.id, (group) => (_jsxs("a", { "data-ui": "catalogue-nav-group", href: pathWithPreferences(`/components/${group.id}`, props.theme, props.density), "aria-current": props.active === group.id ? 'page' : null, children: [_jsx("span", { children: group.name }), _jsx("span", { "data-ui": "catalogue-nav-count", children: String(registrationsFor(group.id).length) })] }))), _jsx("span", { "data-ui": "catalogue-nav-section", children: "Reference" }), _jsxs("a", { "data-ui": "catalogue-nav-group", href: "/surfaces?kind=record&theme=light", children: [_jsx("span", { children: "Page patterns" }), _jsx("span", { "data-ui": "catalogue-nav-count", children: "3" })] }), _jsx("a", { "data-ui": "catalogue-nav-group", href: "/inventory", children: _jsx("span", { children: "Inventory" }) })] })] }));
48
48
  const CataloguePreferences = (props) => (_jsxs("div", { "data-ui": "catalogue-controls", role: "group", "aria-label": "Catalogue preferences", children: [_jsx("span", { children: "Theme" }), each(['light', 'dark', 'system'], (value) => value, (value) => (_jsx("a", { href: pathWithPreferences(props.path, value, props.density), "aria-current": props.theme === value ? 'page' : null, children: value[0].toUpperCase() + value.slice(1) }))), _jsx("span", { children: "Density" }), each(['compact', 'default', 'comfortable'], (value) => value, (value) => (_jsx("a", { href: pathWithPreferences(props.path, props.theme, value), "aria-current": props.density === value ? 'page' : null, children: value === 'comfortable' ? 'Comfort' : value[0].toUpperCase() + value.slice(1) })))] }));
49
49
  const Overview = (props) => (_jsxs(_Fragment, { children: [_jsxs("header", { "data-ui": "catalogue-hero", children: [_jsxs("div", { children: [_jsx("p", { "data-ui": "catalogue-kicker", children: "SSR-first \u00B7 operational \u00B7 accessible" }), _jsx("h1", { "data-ui": "catalogue-title", children: "The interface language for K\u00E9t applications." }), _jsx("p", { "data-ui": "catalogue-intro", children: "Reusable contracts for dense business software\u2014designed to remain useful before JavaScript arrives and predictable when the workflow gets complicated." }), _jsx(LinkButton, { label: `Explore ${String(componentRegistry.length)} components`, href: pathWithPreferences('/components', props.theme, props.density), variant: "primary" }), _jsx(LinkButton, { label: "Review inventory", href: "/inventory", variant: "secondary" }), _jsx(LinkButton, { label: "Open application demo", href: `/demo?theme=${props.theme === 'system' ? 'light' : props.theme}`, variant: "secondary" }), _jsx(LinkButton, { label: "Try submenu navigation", href: `/demo2?theme=${props.theme === 'system' ? 'light' : props.theme}`, variant: "secondary" })] }), _jsx(CataloguePreferences, { path: "/", theme: props.theme, density: props.density })] }), _jsxs("section", { "data-ui": "catalogue-metrics", "aria-label": "Design system summary", children: [_jsxs("article", { children: [_jsx("strong", { children: String(componentRegistry.length) }), _jsx("span", { children: "public components" })] }), _jsxs("article", { children: [_jsx("strong", { children: String(componentGroups.reduce((total, group) => total + group.examples.length, 0)) }), _jsx("span", { children: "executable specimens" })] }), _jsxs("article", { children: [_jsx("strong", { children: String(componentGroups.length) }), _jsx("span", { children: "documented groups" })] }), _jsxs("article", { children: [_jsx("strong", { children: String(designSystemInventory.summary.plannedComponents) }), _jsx("span", { children: "planned contracts" })] })] }), _jsxs("section", { "data-ui": "catalogue-group", children: [_jsxs("header", { "data-ui": "catalogue-group-head", children: [_jsxs("div", { children: [_jsx("p", { "data-ui": "catalogue-kicker", children: "System map" }), _jsx("h2", { children: "Start with the contract" })] }), _jsx("p", { children: "Use the smallest stable layer that owns the behavior. Recipes compose components; applications own business state." })] }), _jsxs("div", { "data-ui": "catalogue-doc-grid", children: [_jsxs("article", { "data-ui": "catalogue-doc-card", children: [_jsx("span", { children: "01" }), _jsx("h3", { children: "Foundations" }), _jsx("p", { children: "Semantic tokens, density, focus, motion and responsive rules form one cascade." }), _jsx("a", { href: "/inventory#css", children: "Inspect CSS ownership \u2192" })] }), _jsxs("article", { "data-ui": "catalogue-doc-card", children: [_jsx("span", { children: "02" }), _jsx("h3", { children: "Components" }), _jsxs("p", { children: [String(componentRegistry.length), " renderer contracts with explicit owners, states and specimens."] }), _jsx("a", { href: pathWithPreferences('/components', props.theme, props.density), children: "Browse components \u2192" })] }), _jsxs("article", { "data-ui": "catalogue-doc-card", children: [_jsx("span", { children: "03" }), _jsx("h3", { children: "Page patterns" }), _jsx("p", { children: "ListPage, RecordPage and WorkspacePage are the only full-page identities." }), _jsx("a", { href: "/surfaces?kind=record&theme=light", children: "Review page surfaces \u2192" })] })] })] }), _jsxs("section", { "data-ui": "catalogue-group", children: [_jsxs("header", { "data-ui": "catalogue-group-head", children: [_jsxs("div", { children: [_jsx("p", { "data-ui": "catalogue-kicker", children: "Component library" }), _jsx("h2", { children: "Explore the system" })] }), _jsx("p", { children: "Every number below is a component contract, not a specimen card." })] }), _jsx("div", { "data-ui": "catalogue-doc-grid", children: each(componentGroups, (group) => group.id, (group) => (_jsxs("a", { "data-ui": "catalogue-doc-card", href: pathWithPreferences(`/components/${group.id}`, props.theme, props.density), children: [_jsx("span", { children: String(registrationsFor(group.id).length).padStart(2, '0') }), _jsx("h3", { children: group.name }), _jsx("p", { children: group.description })] }))) })] })] }));
50
50
  const ComponentIndex = (props) => (_jsxs(_Fragment, { children: [_jsxs("header", { "data-ui": "catalogue-hero", children: [_jsxs("div", { children: [_jsx("p", { "data-ui": "catalogue-kicker", children: "Reference / components" }), _jsxs("h1", { "data-ui": "catalogue-title", children: [String(componentRegistry.length), " public components"] }), _jsx("p", { "data-ui": "catalogue-intro", children: "Search the complete public surface by ownership group. Components may share a specimen, but every contract remains visible here." })] }), _jsx(CataloguePreferences, { path: props.path, theme: props.theme, density: props.density })] }), _jsx("div", { "data-ui": "catalogue-component-index", children: each(componentGroups, (group) => group.id, (group) => (_jsxs("section", { "data-ui": "catalogue-component-list", "aria-labelledby": `${group.id}-title`, children: [_jsxs("header", { children: [_jsx("h2", { id: `${group.id}-title`, children: group.name }), _jsx("span", { children: String(registrationsFor(group.id).length) })] }), each(registrationsFor(group.id), (registration) => registration.name, (registration) => (_jsxs("a", { "data-ui": "catalogue-component-link", href: `${pathWithPreferences(`/components/${group.id}`, props.theme, props.density)}#${registration.specimenId}`, children: [_jsx("strong", { children: registration.name }), _jsx("small", { children: registration.maturity })] })))] }))) })] }));
@@ -1,6 +1,20 @@
1
1
  {
2
2
  "schemaVersion": "ketjs.design-system-inventory-policy.v1",
3
3
  "publicModules": {
4
+ "./data-operations/timeframe-filter/index.tsx": {
5
+ "owner": "Data operations",
6
+ "maturity": "stable",
7
+ "decision": "build",
8
+ "wave": 4,
9
+ "gapTask": "DS-031"
10
+ },
11
+ "./data-display/bar-chart/index.tsx": {
12
+ "owner": "Data display",
13
+ "maturity": "stable",
14
+ "decision": "build",
15
+ "wave": 4,
16
+ "gapTask": "DS-031"
17
+ },
4
18
  "./data-display/data-grid/index.tsx": {
5
19
  "owner": "Data display",
6
20
  "maturity": "stable",
@@ -8,6 +22,13 @@
8
22
  "wave": 4,
9
23
  "gapTask": "DS-031"
10
24
  },
25
+ "./data-display/matrix/index.tsx": {
26
+ "owner": "Data display",
27
+ "maturity": "stable",
28
+ "decision": "build",
29
+ "wave": 4,
30
+ "gapTask": "DS-031"
31
+ },
11
32
  "./data-display/resource-list/index.tsx": {
12
33
  "owner": "Data display",
13
34
  "maturity": "stable",