@cosmicdrift/kumiko-renderer 0.386.0 → 0.388.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.
Files changed (222) hide show
  1. package/LICENSE +21 -57
  2. package/dist/app/action-form-body.d.ts +2 -2
  3. package/dist/app/action-form-body.js +12 -4
  4. package/dist/app/action-form-shim.d.ts +8 -8
  5. package/dist/app/action-form-shim.js +20 -22
  6. package/dist/app/action-form-support.d.ts +1 -0
  7. package/dist/app/action-form-support.js +1 -1
  8. package/dist/app/app-features-context.js +4 -4
  9. package/dist/app/column-renderers.d.ts +7 -9
  10. package/dist/app/column-renderers.js +15 -18
  11. package/dist/app/config-edit-body.js +7 -3
  12. package/dist/app/config-edit-shim.d.ts +7 -8
  13. package/dist/app/config-edit-shim.js +18 -20
  14. package/dist/app/custom-screens.d.ts +3 -3
  15. package/dist/app/custom-screens.js +8 -8
  16. package/dist/app/dashboard-body.d.ts +2 -2
  17. package/dist/app/dashboard-body.js +2 -2
  18. package/dist/app/entity-edit-prefill.d.ts +11 -0
  19. package/dist/app/entity-edit-prefill.js +18 -13
  20. package/dist/app/entity-edit-screen.js +4 -4
  21. package/dist/app/entity-list-screen.js +3 -3
  22. package/dist/app/extension-form-submit.d.ts +1 -1
  23. package/dist/app/extension-form-submit.js +14 -15
  24. package/dist/app/extension-sections.d.ts +29 -28
  25. package/dist/app/extension-sections.js +10 -10
  26. package/dist/app/feature-schema.js +11 -11
  27. package/dist/app/form-schema.js +2 -2
  28. package/dist/app/header-actions-bar.js +2 -2
  29. package/dist/app/kumiko-screen.js +8 -10
  30. package/dist/app/layout-fields.js +1 -1
  31. package/dist/app/list-facets.js +3 -3
  32. package/dist/app/nav.d.ts +10 -10
  33. package/dist/app/nav.js +13 -13
  34. package/dist/app/projection-detail-body.js +4 -4
  35. package/dist/app/projection-detail-shim.d.ts +6 -5
  36. package/dist/app/projection-detail-shim.js +23 -22
  37. package/dist/app/projection-list-body.js +10 -10
  38. package/dist/app/projection-list-shim.d.ts +5 -5
  39. package/dist/app/projection-list-shim.js +17 -18
  40. package/dist/app/qn.js +10 -12
  41. package/dist/app/qualify-screen-id.js +1 -1
  42. package/dist/app/screen-access.js +2 -2
  43. package/dist/app/screen-shared.js +1 -1
  44. package/dist/app/secret-mint-body.js +4 -4
  45. package/dist/app/write-failed-error.js +8 -7
  46. package/dist/components/edit-mounts.d.ts +2 -2
  47. package/dist/components/embedded-list-field.js +5 -5
  48. package/dist/components/grid-cell-for-field.d.ts +1 -1
  49. package/dist/components/reference-create-dialog.js +3 -3
  50. package/dist/components/related-list-section.d.ts +1 -1
  51. package/dist/components/related-list-section.js +15 -2
  52. package/dist/components/render-edit-action-button.d.ts +1 -3
  53. package/dist/components/render-edit-action-button.js +2 -2
  54. package/dist/components/render-edit-logic.js +1 -1
  55. package/dist/components/render-edit-types.d.ts +6 -6
  56. package/dist/components/render-edit.js +74 -73
  57. package/dist/components/render-field.d.ts +7 -7
  58. package/dist/components/render-field.js +62 -61
  59. package/dist/components/render-list.d.ts +42 -43
  60. package/dist/components/render-list.js +93 -84
  61. package/dist/components/use-wizard-form-draft.js +10 -10
  62. package/dist/context/dispatcher-context.js +5 -5
  63. package/dist/context/user-roles-context.js +2 -2
  64. package/dist/flow-diagram/render.js +9 -1
  65. package/dist/headless/apex/index.d.ts +1 -2
  66. package/dist/headless/apex/index.js +5 -6
  67. package/dist/headless/form/form-controller.js +14 -6
  68. package/dist/headless/form/types.d.ts +1 -0
  69. package/dist/headless/form/zod-bridge.js +2 -2
  70. package/dist/headless/format/index.js +89 -64
  71. package/dist/headless/format/money.js +1 -1
  72. package/dist/headless/index.js +2 -2
  73. package/dist/headless/view-model/edit.js +4 -2
  74. package/dist/headless/view-model/list.js +184 -150
  75. package/dist/headless/view-model/types.d.ts +6 -3
  76. package/dist/hooks/live-refetch-scheduler.js +4 -0
  77. package/dist/hooks/reference-limits.js +11 -12
  78. package/dist/hooks/use-list-url-state.d.ts +13 -13
  79. package/dist/hooks/use-list-url-state.js +21 -22
  80. package/dist/hooks/use-query.js +3 -3
  81. package/dist/hooks/use-reference-lookup.d.ts +9 -1
  82. package/dist/hooks/use-reference-lookup.js +32 -19
  83. package/dist/hooks/use-store.js +18 -22
  84. package/dist/hooks/use-stream-handler.js +4 -2
  85. package/dist/i18n-defaults.js +6 -8
  86. package/dist/i18n.d.ts +10 -10
  87. package/dist/i18n.js +25 -25
  88. package/dist/index.d.ts +1 -0
  89. package/dist/index.js +6 -4
  90. package/dist/live/dispatcher-live.js +2 -2
  91. package/dist/primitives.d.ts +244 -221
  92. package/dist/primitives.js +1 -1
  93. package/dist/sse/live-events.d.ts +5 -5
  94. package/dist/sse/live-events.js +17 -17
  95. package/dist/tokens.d.ts +8 -8
  96. package/dist/tokens.js +16 -17
  97. package/dist/web/app/browser-locale.d.ts +9 -9
  98. package/dist/web/app/browser-locale.js +19 -19
  99. package/dist/web/app/client-plugin.d.ts +44 -52
  100. package/dist/web/app/client-plugin.js +4 -5
  101. package/dist/web/app/create-app.d.ts +28 -31
  102. package/dist/web/app/create-app.js +29 -25
  103. package/dist/web/app/dashboard-body.js +17 -1
  104. package/dist/web/app/dashboard-panels.js +12 -2
  105. package/dist/web/app/document-lang-sync.js +1 -1
  106. package/dist/web/app/draft-storage.js +1 -1
  107. package/dist/web/app/nav-providers-context.d.ts +3 -3
  108. package/dist/web/app/nav-providers-context.js +3 -3
  109. package/dist/web/app/nav.d.ts +18 -17
  110. package/dist/web/app/nav.js +66 -64
  111. package/dist/web/app/rich-content-editor.js +1 -1
  112. package/dist/web/components/config-cascade.js +17 -18
  113. package/dist/web/components/config-source-badge.js +4 -4
  114. package/dist/web/index.d.ts +1 -1
  115. package/dist/web/index.js +1 -1
  116. package/dist/web/layout/app-layout.d.ts +9 -9
  117. package/dist/web/layout/app-layout.js +2 -2
  118. package/dist/web/layout/avatar.d.ts +4 -3
  119. package/dist/web/layout/avatar.js +15 -17
  120. package/dist/web/layout/default-app-shell.d.ts +22 -23
  121. package/dist/web/layout/editor-panel.js +3 -3
  122. package/dist/web/layout/nav-tree.js +86 -84
  123. package/dist/web/layout/profile-menu.d.ts +1 -1
  124. package/dist/web/layout/shell-header.js +2 -1
  125. package/dist/web/layout/sidebar-brand.d.ts +7 -7
  126. package/dist/web/layout/sidebar-user.d.ts +1 -1
  127. package/dist/web/layout/sidebar-user.js +4 -4
  128. package/dist/web/layout/sidebar.d.ts +8 -8
  129. package/dist/web/layout/sidebar.js +7 -7
  130. package/dist/web/layout/target-resolver-stub.d.ts +5 -5
  131. package/dist/web/layout/target-resolver-stub.js +20 -20
  132. package/dist/web/layout/target-url.d.ts +7 -7
  133. package/dist/web/layout/target-url.js +22 -22
  134. package/dist/web/layout/theme-toggle.js +4 -5
  135. package/dist/web/layout/uniform-bar-controls.d.ts +1 -0
  136. package/dist/web/layout/uniform-bar-controls.js +4 -0
  137. package/dist/web/layout/workspace-shell.d.ts +21 -21
  138. package/dist/web/layout/workspace-shell.js +29 -30
  139. package/dist/web/lib/cn.d.ts +4 -4
  140. package/dist/web/lib/cn.js +4 -4
  141. package/dist/web/lib/file-ref-download.js +4 -1
  142. package/dist/web/primitives/action-menu.d.ts +8 -8
  143. package/dist/web/primitives/action-menu.js +14 -13
  144. package/dist/web/primitives/calendar-popover.d.ts +1 -1
  145. package/dist/web/primitives/calendar-popover.js +10 -10
  146. package/dist/web/primitives/card-styles.js +1 -1
  147. package/dist/web/primitives/card.js +2 -2
  148. package/dist/web/primitives/code-input.d.ts +6 -0
  149. package/dist/web/primitives/code-input.js +31 -0
  150. package/dist/web/primitives/combobox.d.ts +12 -12
  151. package/dist/web/primitives/combobox.js +34 -35
  152. package/dist/web/primitives/data-table-cell.js +2 -2
  153. package/dist/web/primitives/data-table.js +6 -6
  154. package/dist/web/primitives/date-field.js +2 -2
  155. package/dist/web/primitives/date-input.js +4 -4
  156. package/dist/web/primitives/default-form.js +2 -2
  157. package/dist/web/primitives/dropdown-menu.js +14 -15
  158. package/dist/web/primitives/embedded-list-input.js +3 -3
  159. package/dist/web/primitives/facet-filter.js +2 -2
  160. package/dist/web/primitives/field.js +9 -8
  161. package/dist/web/primitives/file-thumbnail.d.ts +3 -0
  162. package/dist/web/primitives/file-thumbnail.js +5 -0
  163. package/dist/web/primitives/form.d.ts +1 -1
  164. package/dist/web/primitives/form.js +6 -6
  165. package/dist/web/primitives/input.js +8 -3
  166. package/dist/web/primitives/layout-elements.js +7 -5
  167. package/dist/web/primitives/layout.js +2 -2
  168. package/dist/web/primitives/located-timestamp-input.js +4 -4
  169. package/dist/web/primitives/money-input.js +13 -17
  170. package/dist/web/primitives/page-header.js +3 -1
  171. package/dist/web/primitives/pager.js +1 -1
  172. package/dist/web/primitives/row-actions.js +6 -7
  173. package/dist/web/primitives/secret-reveal.js +1 -1
  174. package/dist/web/primitives/timestamp-input.d.ts +9 -9
  175. package/dist/web/primitives/timestamp-input.js +21 -21
  176. package/dist/web/primitives/toast.js +12 -13
  177. package/dist/web/primitives/use-focus-on-mount.d.ts +2 -0
  178. package/dist/web/primitives/use-focus-on-mount.js +9 -0
  179. package/dist/web/sse/live-events.d.ts +6 -6
  180. package/dist/web/sse/live-events.js +3 -3
  181. package/dist/web/tokens.d.ts +11 -12
  182. package/dist/web/tokens.js +35 -37
  183. package/dist/web/version/update-checker.js +14 -13
  184. package/dist/web/widgets/ai-text-field.js +1 -1
  185. package/dist/web/widgets/bounded-load-cache.d.ts +1 -1
  186. package/dist/web/widgets/bounded-load-cache.js +10 -4
  187. package/dist/web/widgets/charts.d.ts +10 -10
  188. package/dist/web/widgets/charts.js +8 -8
  189. package/dist/web/widgets/choice-cards.d.ts +17 -0
  190. package/dist/web/widgets/choice-cards.js +12 -0
  191. package/dist/web/widgets/collapsible-section.d.ts +3 -3
  192. package/dist/web/widgets/collapsible-section.js +7 -7
  193. package/dist/web/widgets/detail-list.d.ts +5 -3
  194. package/dist/web/widgets/detail-list.js +5 -3
  195. package/dist/web/widgets/feed-list.d.ts +2 -2
  196. package/dist/web/widgets/feed-list.js +2 -2
  197. package/dist/web/widgets/form-fields.d.ts +14 -14
  198. package/dist/web/widgets/form-fields.js +14 -13
  199. package/dist/web/widgets/index.d.ts +1 -0
  200. package/dist/web/widgets/index.js +5 -4
  201. package/dist/web/widgets/infinity-list.js +3 -3
  202. package/dist/web/widgets/mode-switch.d.ts +2 -2
  203. package/dist/web/widgets/mode-switch.js +2 -2
  204. package/dist/web/widgets/pdf-preview.js +1 -1
  205. package/dist/web/widgets/plan-card.d.ts +2 -0
  206. package/dist/web/widgets/plan-card.js +1 -1
  207. package/dist/web/widgets/progress-list.d.ts +1 -2
  208. package/dist/web/widgets/progress-list.js +1 -2
  209. package/dist/web/widgets/query-table.d.ts +6 -6
  210. package/dist/web/widgets/result-panel.d.ts +16 -16
  211. package/dist/web/widgets/result-panel.js +10 -10
  212. package/dist/web/widgets/section-card.d.ts +3 -3
  213. package/dist/web/widgets/section-card.js +3 -3
  214. package/dist/web/widgets/stat.d.ts +4 -4
  215. package/dist/web/widgets/stat.js +6 -6
  216. package/dist/web/widgets/states.d.ts +4 -4
  217. package/dist/web/widgets/states.js +4 -4
  218. package/dist/web/widgets/upload-zone.js +13 -5
  219. package/dist/web/widgets/use-draft.d.ts +7 -7
  220. package/dist/web/widgets/use-draft.js +7 -7
  221. package/package.json +6 -6
  222. package/src/changes.json +49 -0
@@ -12,9 +12,9 @@ const SOURCE_I18N_KEY = {
12
12
  default: "kumiko.config.source.default",
13
13
  missing: "kumiko.config.source.missing",
14
14
  };
15
- // Fallback-Reihenfolge der Cascade, spezifischste Quelle zuerst.
16
- // Index-Vergleich gegen die Screen-Scope-Quelle entscheidet, welche
17
- // Ebenen ein Nicht-Operator sehen darf.
15
+ // Fallback order of the cascade, with the most specific source first.
16
+ // Comparing indices with the screen-scope source determines which
17
+ // levels a non-operator may see.
18
18
  const SOURCE_ORDER = [
19
19
  "user-row",
20
20
  "tenant-row",
@@ -51,16 +51,16 @@ function scopeToSource(scope) {
51
51
  return "system-row";
52
52
  }
53
53
  function toDisplayLevels(levels, screenScopeSource) {
54
- // System-Screens sind Operator-Sicht — volle Cascade inkl.
55
- // app-override/computed/default bleibt sichtbar.
54
+ // System screens have operator visibility, so the full cascade, including
55
+ // app-override/computed/default, remains visible.
56
56
  if (screenScopeSource === "system-row") {
57
57
  return levels.map((level) => ({ level, badgeSource: level.source }));
58
58
  }
59
59
  const scopeIdx = SOURCE_ORDER.indexOf(screenScopeSource);
60
60
  const own = levels.filter((l) => SOURCE_ORDER.indexOf(l.source) <= scopeIdx);
61
61
  const higher = levels.filter((l) => SOURCE_ORDER.indexOf(l.source) > scopeIdx);
62
- // Genau eine Fallback-Zeile: die aktive höhere Ebene (deren Wert der
63
- // User effektiv bekommt), sonst der deklarierte Default/Missing.
62
+ // Exactly one fallback row: the active higher level (whose value the user
63
+ // effectively receives), or the declared default/missing level.
64
64
  const fallback = higher.find((l) => l.isActive) ??
65
65
  higher.find((l) => l.source === "default" || l.source === "missing");
66
66
  const ownRows = own.map((level) => ({ level, badgeSource: level.source }));
@@ -71,12 +71,11 @@ function toDisplayLevels(levels, screenScopeSource) {
71
71
  {
72
72
  level: fallback,
73
73
  badgeSource: "default",
74
- // Ein durchgängiger Begriff "Standard" (DE) / "Default" (EN) — derselbe
75
- // Key wie das Feld-Label-Badge (kumiko.config.source.default), damit
76
- // Badge + Cascade-Disclosure NICHT zwei verschiedene Wörter zeigen
77
- // (Bug-Bash 3 #11). Der Screen-Scope kann die Operator-Ebenen
78
- // (System/Override/Computed) weder setzen noch zurücksetzen, deshalb
79
- // erscheinen sie hier neutral als "Standard".
74
+ // Use one consistent term, "Standard" (DE) / "Default" (EN)—the same
75
+ // key as the field-label badge (kumiko.config.source.default), so the
76
+ // badge and cascade disclosure do not show two different words. The
77
+ // screen scope cannot set or reset the operator levels (System/Override/
78
+ // Computed), so they appear here neutrally as "Standard".
80
79
  badgeLabelKey: "kumiko.config.source.default",
81
80
  },
82
81
  ];
@@ -106,11 +105,11 @@ export function ConfigCascadeView({ cascade, screenScope, onReset, qualifiedKey,
106
105
  const displayLevels = toDisplayLevels(cascade.levels, screenScopeSource);
107
106
  const activeDisplay = displayLevels.find((d) => d.level.isActive);
108
107
  const hasOverride = activeDisplay?.level.source === screenScopeSource;
109
- // Aufklappbar nur wenn das Panel echten Mehrwert bringt: ein eigener
110
- // Override (→ Reset) oder mehr als eine Ebene MIT Wert. Leere Ebenen
111
- // (z.B. die ungesetzte tenant-row eines reinen Default-Felds) zählen
112
- // nicht — sonst wäre ein Feld, das nur seinen Standard zeigt, fälschlich
113
- // aufklappbar und das Panel nur eine Wiederholung des Triggers.
108
+ // Expandable only when the panel provides meaningful additional information:
109
+ // an own override (→ Reset) or more than one level with a value. Empty levels
110
+ // (e.g. the unset tenant-row of a field using only its default) do not count;
111
+ // otherwise a field showing only its default would incorrectly be expandable,
112
+ // making the panel merely repeat the trigger.
114
113
  const valuedLevels = displayLevels.filter((d) => d.level.hasValue);
115
114
  const expandable = hasOverride || valuedLevels.length > 1;
116
115
  const isUnset = activeDisplay === undefined || !activeDisplay.level.hasValue;
@@ -40,10 +40,10 @@ function scopeToSource(scope) {
40
40
  }
41
41
  export function ConfigSourceBadge({ source, screenScope, }) {
42
42
  const t = useTranslation();
43
- // Gleiche Kollaps-Regel wie toDisplayLevels (config-cascade.tsx):
44
- // Operator-Quellen oberhalb des Screen-Scopes erscheinen für Nicht-
45
- // Operator-Screens als neutrales "Vorgabe"-Badge — sonst leakte das
46
- // Badge die System-Quelle, die die Cascade-View bewusst versteckt.
43
+ // Uses the same collapsing rule as toDisplayLevels (config-cascade.tsx):
44
+ // for non-operator screens, operator sources above the screen scope appear
45
+ // as a neutral "Vorgabe" badge so the badge does not reveal the system source
46
+ // intentionally hidden by the cascade view.
47
47
  let effective = source;
48
48
  if (screenScope !== undefined && screenScope !== "system") {
49
49
  const scopeIdx = SOURCE_ORDER.indexOf(scopeToSource(screenScope));
@@ -75,4 +75,4 @@ export { SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider } from
75
75
  export type { KumikoBuild } from "./version/update-checker.tsx";
76
76
  export { readLoadedBuild } from "./version/update-checker.tsx";
77
77
  export type { AiTextAreaProps, AiTextFieldProps, BooleanFieldProps, ComparisonMetric, DateFieldProps, DrawerProps, FeedRow, FileFieldProps, FloatingPanelGeometry, FloatingPanelProps, InfinityListProps, InfinityListSelection, ModeSwitchVariant, NumberFieldProps, PdfPreviewSource, PhotoSlotSpec, PhotoSlotsProps, PlanCardActionSlot, PlanCardLinkSlot, PlanCardPrice, PlanCardProps, PlanGridProps, ProgressListRow, PublicShellProps, PublicShellVariant, QueryTableColumn, QueryTableProps, RangeFieldProps, ResultColumn, SelectFieldProps, SideBySideTableCell, SideBySideTableColumn, SideBySideTableRow, StatDelta, StatTone, StatusBadgeTone, StatusBarEntry, StatusTone, TextareaFieldProps, TextFieldProps, TimeseriesHeight, TimeseriesPoint, TimeseriesReferenceLine, TimeseriesXAxis, TimeseriesYAxis, UploadZoneProps, } from "./widgets/index.ts";
78
- export { AiTextArea, AiTextField, BooleanField, CollapsibleSection, ComparisonTable, DateField, DetailList, Drawer, EmptyState, ErrorState, FeedList, FileField, FloatingPanel, InfinityList, LoadingState, MiniStat, ModeSwitch, MoneyField, NumberField, PdfPreview, PercentField, PhotoSlots, PlanCard, PlanGrid, ProgressBar, ProgressList, PublicShell, QueryTable, RangeField, ResultPanel, ResultTable, SectionCard, SelectField, SideBySideTable, Sparkline, STATUS_TONE_TEXT, StatCard, StatusBadge, StatusBarChart, StepBar, smoothPath, TextareaField, TextField, TimeseriesChart, UploadZone, useDraft, } from "./widgets/index.ts";
78
+ export { AiTextArea, AiTextField, BooleanField, ChoiceCards, CollapsibleSection, ComparisonTable, DateField, DetailList, Drawer, EmptyState, ErrorState, FeedList, FileField, FloatingPanel, InfinityList, LoadingState, MiniStat, ModeSwitch, MoneyField, NumberField, PdfPreview, PercentField, PhotoSlots, PlanCard, PlanGrid, ProgressBar, ProgressList, PublicShell, QueryTable, RangeField, ResultPanel, ResultTable, SectionCard, SelectField, SideBySideTable, Sparkline, STATUS_TONE_TEXT, StatCard, StatusBadge, StatusBarChart, StepBar, smoothPath, TextareaField, TextField, TimeseriesChart, UploadZone, useDraft, } from "./widgets/index.ts";
package/dist/web/index.js CHANGED
@@ -50,4 +50,4 @@ export { applyTokensToCssVars, defaultTokens, lightTokens, useBrowserTokensApi,
50
50
  export { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "./ui/resizable.js";
51
51
  export { SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider } from "./ui/sidebar.js";
52
52
  export { readLoadedBuild } from "./version/update-checker.js";
53
- export { AiTextArea, AiTextField, BooleanField, CollapsibleSection, ComparisonTable, DateField, DetailList, Drawer, EmptyState, ErrorState, FeedList, FileField, FloatingPanel, InfinityList, LoadingState, MiniStat, ModeSwitch, MoneyField, NumberField, PdfPreview, PercentField, PhotoSlots, PlanCard, PlanGrid, ProgressBar, ProgressList, PublicShell, QueryTable, RangeField, ResultPanel, ResultTable, SectionCard, SelectField, SideBySideTable, Sparkline, STATUS_TONE_TEXT, StatCard, StatusBadge, StatusBarChart, StepBar, smoothPath, TextareaField, TextField, TimeseriesChart, UploadZone, useDraft, } from "./widgets/index.js";
53
+ export { AiTextArea, AiTextField, BooleanField, ChoiceCards, CollapsibleSection, ComparisonTable, DateField, DetailList, Drawer, EmptyState, ErrorState, FeedList, FileField, FloatingPanel, InfinityList, LoadingState, MiniStat, ModeSwitch, MoneyField, NumberField, PdfPreview, PercentField, PhotoSlots, PlanCard, PlanGrid, ProgressBar, ProgressList, PublicShell, QueryTable, RangeField, ResultPanel, ResultTable, SectionCard, SelectField, SideBySideTable, Sparkline, STATUS_TONE_TEXT, StatCard, StatusBadge, StatusBarChart, StepBar, smoothPath, TextareaField, TextField, TimeseriesChart, UploadZone, useDraft, } from "./widgets/index.js";
@@ -1,19 +1,19 @@
1
1
  import type { ReactNode } from "react";
2
2
  export type AppLayoutProps = {
3
- /** Optional. Lebt nur über dem Main-Bereich, nicht über der Sidebar. */
3
+ /** Optional. Exists only above the main area, not above the sidebar. */
4
4
  readonly topbar?: ReactNode;
5
5
  readonly sidebar?: ReactNode;
6
6
  readonly children: ReactNode;
7
7
  readonly testId?: string;
8
- /** Viewport-fit Shell. Default `true` → Wurzel = `h-screen` (fixe
9
- * Viewport-Höhe), Sidebar/Topbar bleiben stehen, der Main-Bereich
10
- * scrollt INNEN (`min-h-0` + `overflow-auto`). `false` → klassischer
11
- * `min-h-screen`-Flow, die ganze Seite scrollt — Escape-Hatch für
12
- * eine öffentliche, lange Content-Seite die echten Body-Scroll
13
- * braucht. Clippt nie — der Content scrollt in `main` statt im Body. */
8
+ /** Viewport-fit shell. Default `true` → root = `h-screen` (fixed
9
+ * viewport height); sidebar/topbar remain fixed while the main area
10
+ * scrolls INSIDE (`min-h-0` + `overflow-auto`). `false` → classic
11
+ * `min-h-screen` flow where the whole page scrolls—an escape hatch for
12
+ * a public, long content page that needs real body scrolling. Never
13
+ * clips—content scrolls in `main` instead of the body. */
14
14
  readonly fill?: boolean;
15
- /** Optionaler Klassen-Append an die Wurzel (eigener Hintergrund etc.).
16
- * Erweitert die Defaults, ersetzt sie nicht (cn-merge). */
15
+ /** Optional classes appended to the root (for a custom background, etc.).
16
+ * Extends the defaults rather than replacing them (`cn` merge). */
17
17
  readonly className?: string;
18
18
  /** Optionaler Klassen-Append an `<main>`. */
19
19
  readonly mainClassName?: string;
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../lib/cn.js";
3
3
  export function AppLayout({ topbar, sidebar, children, testId, fill = true, className, mainClassName, }) {
4
4
  return (_jsxs("div", { "data-testid": testId, "data-kumiko-layout": "app", ...(fill === true && { "data-kumiko-fill": "true" }), className: cn(
5
- // new-york inset-Frame: gedämpfter Rail-Background, die Sidebar sitzt
6
- // transparent darauf, der Main-Bereich schwebt als eigenes Panel.
5
+ // new-york inset frame: muted rail background; the sidebar sits
6
+ // transparently on it, while the main area floats as its own panel.
7
7
  "flex flex-row bg-muted/40 text-foreground", fill === true ? "h-screen" : "min-h-screen", className), children: [sidebar, _jsxs("div", { className: cn("flex flex-1 min-w-0 flex-col overflow-hidden rounded-xl border bg-background shadow-sm m-2 md:ml-0", fill === true && "min-h-0"), children: [topbar, _jsx("main", { className: cn("flex-1 overflow-auto", fill === true && "min-h-0", mainClassName), children: children })] })] }));
8
8
  }
@@ -1,10 +1,11 @@
1
1
  import { type ReactNode } from "react";
2
2
  export type AvatarSize = "sm" | "md" | "lg";
3
3
  export type AvatarProps = {
4
- /** Stable Identifier — Hash-Quelle für die Background-Farbe. Üblich
5
- * user.id; bei rein labelbasierten Avataren auch der label-String. */
4
+ /** Stable identifier—the source for the background-color hash. Usually
5
+ * `user.id`; for avatars based only on a label, the label string can also
6
+ * be used. */
6
7
  readonly id: string;
7
- /** Voller Name oder Email — Initials werden daraus extrahiert. */
8
+ /** Full name or email—the initials are extracted from this value. */
8
9
  readonly label: string;
9
10
  readonly size?: AvatarSize;
10
11
  readonly testId?: string;
@@ -1,20 +1,18 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- // Avatar-Pill mit Initials. Color-coded background basierend auf
3
- // string-hash damit der gleiche User immer dieselbe Farbe bekommt
4
- // (Linear-Pattern). 8 Hue-Targets für gute Distinktion ohne über-
5
- // bunte Sidebar.
2
+ // Avatar pill with initials. The color is based on a string hash so the same
3
+ // user always gets the same color (linear pattern). Eight hue targets provide
4
+ // good distinction without making the sidebar overly colorful.
6
5
  //
7
- // Nutzung: `<Avatar id="user-123" label="Daniel Hennig" size="md" />`.
8
- // `id` ist die Hash-Quelle für die Farbe; `label` wird für Initials
9
- // + aria-label genutzt. Kein Image-Slot im MVP — kommt wenn Apps
10
- // echte Avatar-URLs haben.
6
+ // Usage: `<Avatar id="user-123" label="Daniel Hennig" size="md" />`.
7
+ // `id` is the color's hash source; `label` is used for initials and the
8
+ // aria-label. There is no image slot yet; one follows once apps provide real
9
+ // avatar URLs.
11
10
  import { useMemo } from "react";
12
11
  import { cn } from "../lib/cn.js";
13
- // Tailwind-Klassen pro Hue. Die Background-Lightness ist dezent (550-
14
- // 600 für saturation), die Foreground-Lightness ist hell (50-100) für
15
- // Kontrast. Passt zu beiden Modes weil die Tokens via CSS-vars greifen
16
- // — aber: feste hex-Farben hier sind stabiler als token-mapping
17
- // (Avatar-Farbe sollte deterministic sein, nicht theme-abhängig).
12
+ // Tailwind classes for each hue. Background lightness is moderate (550–600)
13
+ // for saturation, while foreground lightness is high (50–100) for contrast.
14
+ // Fixed colors keep avatar colors deterministic and independent of the theme,
15
+ // even though the tokens work in both modes through CSS variables.
18
16
  const COLOR_CLASSES = [
19
17
  "bg-rose-600 text-rose-50",
20
18
  "bg-orange-600 text-orange-50",
@@ -31,8 +29,8 @@ const SIZE_CLASSES = {
31
29
  lg: "size-8 text-xs",
32
30
  };
33
31
  function hashCode(str) {
34
- // djb2-Variante — schnell, deterministic, gut genug verteilt für
35
- // 8 Buckets. Crypto-Hash wäre Overkill für color-bucketing.
32
+ // A djb2 variant: fast and sufficiently well distributed for 8 buckets.
33
+ // A cryptographic hash would be overkill for color bucketing.
36
34
  let hash = 5381;
37
35
  for (let i = 0; i < str.length; i++) {
38
36
  hash = ((hash << 5) + hash + str.charCodeAt(i)) >>> 0;
@@ -44,8 +42,8 @@ function pickColor(id) {
44
42
  return COLOR_CLASSES[idx] ?? COLOR_CLASSES[0] ?? "bg-muted";
45
43
  }
46
44
  function extractInitials(label) {
47
- // "Daniel Hennig" → "DH". "alice@example.com" → "AL". Single-word
48
- // fällt auf erste 2 Buchstaben zurück ("Daniel" → "DA"). Alles
45
+ // "Daniel Hennig" → "DH". "alice@example.com" → "AL". For a single word,
46
+ // it falls back to the first 2 letters ("Daniel" → "DA"). Everything is
49
47
  // upper-case.
50
48
  const trimmed = label.trim();
51
49
  if (trimmed.length === 0)
@@ -5,37 +5,36 @@ export type DefaultAppShellUser = {
5
5
  readonly roles: readonly string[];
6
6
  };
7
7
  export type DefaultAppShellProps = {
8
- /** Header-Slot oben in der Sidebar — Workspace-Identity (Logo, Name,
9
- * Plan-Tag). Caller liefert frei. */
8
+ /** Header slot at the top of the sidebar — workspace identity (logo, name,
9
+ * plan tag). The caller provides the content. */
10
10
  readonly brand: ReactNode;
11
- /** Schema (AppSchema oder legacy FeatureSchema) wird an NavTree
12
- * durchgereicht; Sidebar-Einträge bauen sich automatisch aus
13
- * schema.navs (per-Feature) auf. */
11
+ /** Schema (AppSchema or legacy FeatureSchema) passed through to NavTree;
12
+ * sidebar entries are generated automatically from
13
+ * schema.navs (per-feature). */
14
14
  readonly schema: AppSchema | FeatureSchema;
15
- /** Current user — drives nav role-gating. Ohne user-prop werden
16
- * role-gated nav-einträge (`access: { roles: [...] }`) komplett
17
- * ausgeblendet (resolveNavigation behandelt undefined-user als
18
- * anonymous). */
15
+ /** Current user — drives navigation role gating. Without a user prop,
16
+ * role-gated navigation entries (`access: { roles: [...] }`) are hidden
17
+ * completely (resolveNavigation treats an undefined user as anonymous). */
19
18
  readonly user?: DefaultAppShellUser;
20
- /** Icon-Row zwischen Brand und NavTree — typisch Search-Trigger,
21
- * ThemeToggle, TenantSwitcher. */
19
+ /** Icon row between the brand and NavTree — typically a Search trigger,
20
+ * ThemeToggle, or TenantSwitcher. */
22
21
  readonly sidebarActions?: ReactNode;
23
- /** Runtime-Badges pro Nav-Item (bare nav-id → ReactNode), an NavTree
24
- * durchgereicht. Für Tier-/Status-Badges, die die App pro User liefert
25
- * (Wert + Farbe), statt sie ins statische Schema zu backen. */
22
+ /** Runtime badges per navigation item (bare nav-id → ReactNode), passed
23
+ * through to NavTree. For tier/status badges supplied by the app per user
24
+ * (value + color), rather than embedded in the static schema. */
26
25
  readonly navBadges?: ReadonlyMap<string, ReactNode>;
27
- /** Rechtsbündiger Slot in der Topbar (neben dem Breadcrumb) — für
28
- * ThemeToggle, globale Actions o.ä. Spart die eigene sidebarActions-
29
- * Zeile in der Sidebar. */
26
+ /** Right-aligned slot in the topbar (next to the breadcrumb) — for
27
+ * ThemeToggle, global actions, and similar controls. Avoids a separate
28
+ * sidebarActions row in the sidebar. */
30
29
  readonly headerActions?: ReactNode;
31
- /** Footer-Slot unten in der Sidebar — Profile-Row, Help-Link,
32
- * Plan-Banner. */
30
+ /** Footer slot at the bottom of the sidebar — profile row, help link,
31
+ * or plan banner. */
33
32
  readonly sidebarFooter?: ReactNode;
34
- /** Viewport-fit Shell. true → fixe Viewport-Höhe (`h-svh`), der Content
35
- * scrollt INNEN statt der ganzen Seite. Default true — `fill={false}`
36
- * schaltet zurück auf Seiten-Scroll. */
33
+ /** Viewport-fit shell. true → fixed viewport height (`h-svh`); content
34
+ * scrolls inside instead of the whole page. Defaults to true — `fill={false}`
35
+ * switches back to page scrolling. */
37
36
  readonly fill?: boolean;
38
- /** Screen-Content der im SidebarInset gerendert wird. */
37
+ /** Screen content rendered inside SidebarInset. */
39
38
  readonly children: ReactNode;
40
39
  };
41
40
  export declare function DefaultAppShell({ brand, schema, user, sidebarActions, headerActions, navBadges, sidebarFooter, fill, children, }: DefaultAppShellProps): ReactNode;
@@ -15,9 +15,9 @@ function EditorPanelInner({ target, resolvers, onClose, }) {
15
15
  }
16
16
  export function EditorPanel({ resolvers }) {
17
17
  const nav = useNav();
18
- // target derived from URL → F5/Back stellen state wieder her.
19
- // useMemo stabilisiert reference solange searchParams shallow-gleich
20
- // sind (nav-Impl liefert plain-record für genau diesen check).
18
+ // target is derived from the URL, so F5 and Back restore the state.
19
+ // useMemo keeps the reference stable while searchParams are shallow-equal
20
+ // (the nav implementation provides a plain record for this check).
21
21
  const target = useMemo(() => parseTargetFromSearchParams(nav.searchParams), [nav.searchParams]);
22
22
  const handleClose = useCallback(() => {
23
23
  requestLeave(() => nav.setSearchParams(clearTargetSearchParams(nav.searchParams)));