@stll/ui 0.54.0 → 0.55.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 (41) hide show
  1. package/dist/components/alert-dialog.d.ts +2 -2
  2. package/dist/components/button.d.ts +3 -2
  3. package/dist/components/button.js +6 -4
  4. package/dist/components/combobox.d.ts +1 -1
  5. package/dist/components/command.d.ts +3 -3
  6. package/dist/components/composer-tokens.d.ts +72 -0
  7. package/dist/components/composer-tokens.js +73 -0
  8. package/dist/components/composer.d.ts +3 -71
  9. package/dist/components/composer.js +1 -70
  10. package/dist/components/copy-button.d.ts +1 -1
  11. package/dist/components/date-picker-popover.d.ts +1 -1
  12. package/dist/components/destructive-action-confirmation.d.ts +1 -1
  13. package/dist/components/dialog.d.ts +2 -2
  14. package/dist/components/document-identity-badge.js +30 -16
  15. package/dist/components/document-identity-badge.logic.d.ts +23 -4
  16. package/dist/components/document-identity-badge.logic.js +17 -1
  17. package/dist/components/input-group.d.ts +1 -1
  18. package/dist/components/input.d.ts +1 -1
  19. package/dist/components/list.d.ts +1 -1
  20. package/dist/components/pagination.d.ts +1 -1
  21. package/dist/components/popover.d.ts +1 -1
  22. package/dist/components/preview-pane.d.ts +13 -1
  23. package/dist/components/preview-pane.js +16 -4
  24. package/dist/components/search-field.d.ts +1 -1
  25. package/dist/components/select.d.ts +1 -1
  26. package/dist/components/sidebar.d.ts +1 -1
  27. package/dist/components/sidebar.js +10 -4
  28. package/dist/components/split-button.d.ts +1 -1
  29. package/dist/components/textarea.d.ts +1 -1
  30. package/dist/components/toast.d.ts +20 -5
  31. package/dist/components/toast.js +25 -12
  32. package/dist/data-table/index.d.ts +1 -1
  33. package/dist/index.d.ts +60 -60
  34. package/dist/index.js +2 -2
  35. package/dist/inspector/index.d.ts +2 -2
  36. package/dist/kanban/column-bands.d.ts +1 -1
  37. package/dist/kanban/index.d.ts +9 -9
  38. package/dist/kanban/subgroup-board.d.ts +1 -1
  39. package/dist/kanban/virtual-cell.d.ts +1 -1
  40. package/dist/lib/utils.d.ts +1 -1
  41. package/package.json +7 -1
@@ -1,6 +1,6 @@
1
- import { OverlayLayer } from "../lib/overlay-layer.js";
2
- import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
3
1
  import * as React$1 from "react";
2
+ import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
3
+ import { OverlayLayer } from "../lib/overlay-layer.js";
4
4
  //#region src/components/alert-dialog.d.ts
5
5
  declare const AlertDialogCreateHandle: typeof AlertDialog$1.createHandle;
6
6
  declare const AlertDialog: typeof AlertDialog$1.Root;
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from "react";
2
- import { useRender } from "@base-ui/react/use-render";
3
2
  import { VariantProps } from "class-variance-authority";
3
+ import { useRender } from "@base-ui/react/use-render";
4
4
  //#region src/components/button.d.ts
5
5
  /**
6
6
  * Disabled styling for a button that is only `aria-disabled`.
@@ -52,7 +52,8 @@ type ButtonProps = {
52
52
  loading?: boolean;
53
53
  icon?: ReactNode;
54
54
  tooltip?: ReactNode;
55
+ "data-accessible-disabled"?: "";
55
56
  } & useRender.ComponentProps<"button">;
56
- declare function Button({ className, variant, size, render, loading, icon, children, disabled, tooltip, ...props }: ButtonProps): import("react").JSX.Element;
57
+ declare function Button({ className, variant, size, render, loading, icon, children, disabled, tooltip, "data-accessible-disabled": accessibleDisabled, ...props }: ButtonProps): import("react").JSX.Element;
57
58
  //#endregion
58
59
  export { BUTTON_CONTENT, BUTTON_SIZE_CONTENT, Button, buttonAccessibleDisabledClass, buttonVariants };
@@ -102,7 +102,7 @@ const implicitTooltip = (size, accessibleName) => {
102
102
  default: return panic(`Unhandled button content: ${String(content)}`);
103
103
  }
104
104
  };
105
- function Button({ className, variant, size, render, loading, icon, children, disabled, tooltip, ...props }) {
105
+ function Button({ className, variant, size, render, loading, icon, children, disabled, tooltip, "data-accessible-disabled": accessibleDisabled, ...props }) {
106
106
  const typeValue = render ? void 0 : "button";
107
107
  const tooltipContent = tooltip ?? implicitTooltip(size, props["aria-label"] ?? props.title);
108
108
  const disposition = resolveButtonDisposition({
@@ -111,6 +111,7 @@ function Button({ className, variant, size, render, loading, icon, children, dis
111
111
  tooltip: tooltipContent
112
112
  });
113
113
  const isAccessibleDisabled = disposition === BUTTON_DISPOSITION.accessibleDisabled;
114
+ const isActivationPreservingDisabled = accessibleDisabled !== void 0;
114
115
  const defaultProps = {
115
116
  children: /* @__PURE__ */ jsxs(Fragment, { children: [loading ? /* @__PURE__ */ jsx(Loader, {
116
117
  animation: "none",
@@ -119,18 +120,19 @@ function Button({ className, variant, size, render, loading, icon, children, dis
119
120
  size: "sm",
120
121
  variant: "decorative"
121
122
  }) : icon, children] }),
122
- className: cn(disposition === BUTTON_DISPOSITION.enabled && size !== "row" && variant !== "link" && buttonPressClass, buttonVariants({
123
+ className: cn(disposition === BUTTON_DISPOSITION.enabled && !isActivationPreservingDisabled && size !== "row" && variant !== "link" && buttonPressClass, buttonVariants({
123
124
  className,
124
125
  size,
125
126
  variant
126
- }), isAccessibleDisabled && "cursor-not-allowed opacity-64"),
127
+ }), (isAccessibleDisabled || isActivationPreservingDisabled) && "cursor-not-allowed opacity-64"),
127
128
  "data-slot": "button",
128
129
  "aria-busy": loading || void 0,
129
- ...isAccessibleDisabled ? {
130
+ ...isAccessibleDisabled || isActivationPreservingDisabled ? {
130
131
  "aria-disabled": true,
131
132
  "data-disabled": "",
132
133
  tabIndex: 0
133
134
  } : { disabled: disposition === BUTTON_DISPOSITION.nativeDisabled },
135
+ "data-accessible-disabled": accessibleDisabled,
134
136
  type: typeValue
135
137
  };
136
138
  const button = useRender({
@@ -1,6 +1,6 @@
1
- import { ControlSize } from "../lib/control-size.js";
2
1
  import * as React$1 from "react";
3
2
  import { Combobox as Combobox$1 } from "@base-ui/react/combobox";
3
+ import { ControlSize } from "../lib/control-size.js";
4
4
  //#region src/components/combobox.d.ts
5
5
  declare const Combobox: <Value, Multiple extends boolean | undefined = false>(props: Combobox$1.Root.Props<Value, Multiple>) => React$1.JSX.Element;
6
6
  declare const ComboboxChipsInput: ({ className, size, ...props }: Omit<Combobox$1.Input.Props, "size"> & {
@@ -1,9 +1,9 @@
1
- import { ControlSize } from "../lib/control-size.js";
2
- import { DialogContent as DialogPopup } from "./dialog.js";
3
1
  import * as React$1 from "react";
2
+ import { Autocomplete } from "@base-ui/react/autocomplete";
3
+ import { ControlSize } from "../lib/control-size.js";
4
4
  import { Dialog } from "@base-ui/react/dialog";
5
+ import { DialogContent as DialogPopup } from "./dialog.js";
5
6
  import { VariantProps } from "class-variance-authority";
6
- import { Autocomplete } from "@base-ui/react/autocomplete";
7
7
  //#region src/components/command.d.ts
8
8
  type CommandProps<ItemValue> = Omit<Autocomplete.Root.Props<ItemValue>, "items"> & {
9
9
  items?: readonly ItemValue[] | undefined;
@@ -0,0 +1,72 @@
1
+ //#region src/components/composer-tokens.d.ts
2
+ /**
3
+ * The tokens every composer box shares: the chat hero, the chat follow-up
4
+ * bar, the docked bar over documents (inspector chat, file overlay,
5
+ * Template Studio) and the law home's entry box all render one shell from
6
+ * these, so they restyle together. A surface that needs the look imports
7
+ * these rather than copying the classes; a copy is how the boxes drifted
8
+ * apart the first time (44px / `rounded-lg` / 14px in the chat, 38px /
9
+ * `rounded-2xl` / 13px in the inspector).
10
+ */
11
+ /** Shared responsive size for the two round controls flanking a composer. */
12
+ export declare const COMPOSER_CONTROL_BUTTON_SIZE: "icon-sm";
13
+ /** The bordered box: background, radius, border, colour transition. The
14
+ * radius is the docked bar's original `rounded-2xl`: at the compact row's
15
+ * stature it reads as a soft pill, which is the shape the composers were
16
+ * meant to unify on. */
17
+ export declare const COMPOSER_BOX_CLASS = "bg-background rounded-2xl border";
18
+ /** The box's focus ring in its default (non-anonymized) treatment. */
19
+ export declare const COMPOSER_BOX_FOCUS_CLASS = "focus-within:border-ring";
20
+ /**
21
+ * The box's "shield active" treatment when the next send is anonymized: a
22
+ * blue ring replaces the default focus border (both together read as a
23
+ * double ring on click).
24
+ */
25
+ export declare const COMPOSER_BOX_ANONYMIZED_CLASS = "ring-info/40 border-info/40 focus-within:border-info/60 shadow-[0_0_0_4px_rgb(from_var(--color-info)_r_g_b_/_0.08)] ring-1";
26
+ /**
27
+ * The compact (one-line) bar row: its stature, end alignment, control gap
28
+ * and inset. The surface supplies the layout (`grid` for the chat bar's
29
+ * three fixed columns, `flex` for the docked bar's variable leading
30
+ * controls); the row grows with the editor.
31
+ */
32
+ export declare const COMPOSER_COMPACT_ROW_CLASS = "min-h-11 items-end gap-1 px-1.5 py-px";
33
+ /**
34
+ * The compact text cell: one `text-sm` line at `leading-5` plus the
35
+ * vertical inset that makes a single line exactly as tall as the row's
36
+ * inner height (44px row, 1px inset each side ⇒ 42px), so text and controls
37
+ * share one centre. The editable element itself takes `min-h-0` so an empty
38
+ * composer collapses to this one line and grows from there.
39
+ */
40
+ export declare const COMPOSER_COMPACT_TEXT_CELL_CLASS = "relative min-w-0 py-[11px]";
41
+ /** Text stature of the editor and every placeholder painted over it. */
42
+ export declare const COMPOSER_TEXT_CLASS = "text-sm leading-5";
43
+ /**
44
+ * The `large` (hero) text well: the padding around the editor. The editor's
45
+ * own stature is `COMPOSER_LARGE_EDITOR_CLASS` (~3 lines of `text-sm` at
46
+ * `leading-5`), applied on the editable element by each surface because the
47
+ * chat editor targets its `.ProseMirror` node while a plain textarea takes
48
+ * it directly.
49
+ */
50
+ export declare const COMPOSER_LARGE_TEXT_WELL_CLASS = "ps-3 pe-3 pt-2 pb-1";
51
+ /** The `large` editable element's stature: three lines before it grows. */
52
+ export declare const COMPOSER_LARGE_EDITOR_CLASS = "min-h-15";
53
+ /** The placeholder painted over an empty editor, in either stature. */
54
+ export declare const COMPOSER_PLACEHOLDER_CLASS = "text-foreground-placeholder pointer-events-none absolute truncate text-sm";
55
+ /** The `large` action row under the text well: leading controls, trailing send. */
56
+ export declare const COMPOSER_LARGE_ACTION_ROW_CLASS = "flex items-center justify-end gap-0.5 px-1.5 pb-1.5";
57
+ /** The leading group of the action row (the (+) menu, or a scope control). */
58
+ export declare const COMPOSER_LEADING_GROUP_CLASS = "flex min-w-0 items-center gap-0.5";
59
+ /**
60
+ * The round, foreground-filled primary control at the action row's end:
61
+ * the chat's send/stop/retry button and the law home's submit. `size-7`
62
+ * pins the circle to the (+) trigger's diameter at every breakpoint
63
+ * (`icon-sm` alone is 32px below `sm`), so a row's two round ends match.
64
+ */
65
+ export declare const COMPOSER_SEND_BUTTON_CLASS = "bg-foreground text-background hover:bg-foreground/90 size-7 shrink-0 rounded-full";
66
+ /**
67
+ * A picker in the status row under the box (the chat's matter picker, the
68
+ * law home's scope and jurisdiction): quiet text with a hover surface, so
69
+ * the row stays subordinate to the box above it.
70
+ */
71
+ export declare const COMPOSER_PICKER_TRIGGER_CLASS = "text-muted-foreground hover:text-foreground hover:bg-accent inline-flex min-w-0 shrink items-center gap-1 rounded-md px-1.5 py-0.5 text-2xs";
72
+ //#endregion
@@ -0,0 +1,73 @@
1
+ //#region src/components/composer-tokens.ts
2
+ /**
3
+ * The tokens every composer box shares: the chat hero, the chat follow-up
4
+ * bar, the docked bar over documents (inspector chat, file overlay,
5
+ * Template Studio) and the law home's entry box all render one shell from
6
+ * these, so they restyle together. A surface that needs the look imports
7
+ * these rather than copying the classes; a copy is how the boxes drifted
8
+ * apart the first time (44px / `rounded-lg` / 14px in the chat, 38px /
9
+ * `rounded-2xl` / 13px in the inspector).
10
+ */
11
+ /** Shared responsive size for the two round controls flanking a composer. */
12
+ const COMPOSER_CONTROL_BUTTON_SIZE = "icon-sm";
13
+ /** The bordered box: background, radius, border, colour transition. The
14
+ * radius is the docked bar's original `rounded-2xl`: at the compact row's
15
+ * stature it reads as a soft pill, which is the shape the composers were
16
+ * meant to unify on. */
17
+ const COMPOSER_BOX_CLASS = "bg-background rounded-2xl border";
18
+ /** The box's focus ring in its default (non-anonymized) treatment. */
19
+ const COMPOSER_BOX_FOCUS_CLASS = "focus-within:border-ring";
20
+ /**
21
+ * The box's "shield active" treatment when the next send is anonymized: a
22
+ * blue ring replaces the default focus border (both together read as a
23
+ * double ring on click).
24
+ */
25
+ const COMPOSER_BOX_ANONYMIZED_CLASS = "ring-info/40 border-info/40 focus-within:border-info/60 shadow-[0_0_0_4px_rgb(from_var(--color-info)_r_g_b_/_0.08)] ring-1";
26
+ /**
27
+ * The compact (one-line) bar row: its stature, end alignment, control gap
28
+ * and inset. The surface supplies the layout (`grid` for the chat bar's
29
+ * three fixed columns, `flex` for the docked bar's variable leading
30
+ * controls); the row grows with the editor.
31
+ */
32
+ const COMPOSER_COMPACT_ROW_CLASS = "min-h-11 items-end gap-1 px-1.5 py-px";
33
+ /**
34
+ * The compact text cell: one `text-sm` line at `leading-5` plus the
35
+ * vertical inset that makes a single line exactly as tall as the row's
36
+ * inner height (44px row, 1px inset each side ⇒ 42px), so text and controls
37
+ * share one centre. The editable element itself takes `min-h-0` so an empty
38
+ * composer collapses to this one line and grows from there.
39
+ */
40
+ const COMPOSER_COMPACT_TEXT_CELL_CLASS = "relative min-w-0 py-[11px]";
41
+ /** Text stature of the editor and every placeholder painted over it. */
42
+ const COMPOSER_TEXT_CLASS = "text-sm leading-5";
43
+ /**
44
+ * The `large` (hero) text well: the padding around the editor. The editor's
45
+ * own stature is `COMPOSER_LARGE_EDITOR_CLASS` (~3 lines of `text-sm` at
46
+ * `leading-5`), applied on the editable element by each surface because the
47
+ * chat editor targets its `.ProseMirror` node while a plain textarea takes
48
+ * it directly.
49
+ */
50
+ const COMPOSER_LARGE_TEXT_WELL_CLASS = "ps-3 pe-3 pt-2 pb-1";
51
+ /** The `large` editable element's stature: three lines before it grows. */
52
+ const COMPOSER_LARGE_EDITOR_CLASS = "min-h-15";
53
+ /** The placeholder painted over an empty editor, in either stature. */
54
+ const COMPOSER_PLACEHOLDER_CLASS = "text-foreground-placeholder pointer-events-none absolute truncate text-sm";
55
+ /** The `large` action row under the text well: leading controls, trailing send. */
56
+ const COMPOSER_LARGE_ACTION_ROW_CLASS = "flex items-center justify-end gap-0.5 px-1.5 pb-1.5";
57
+ /** The leading group of the action row (the (+) menu, or a scope control). */
58
+ const COMPOSER_LEADING_GROUP_CLASS = "flex min-w-0 items-center gap-0.5";
59
+ /**
60
+ * The round, foreground-filled primary control at the action row's end:
61
+ * the chat's send/stop/retry button and the law home's submit. `size-7`
62
+ * pins the circle to the (+) trigger's diameter at every breakpoint
63
+ * (`icon-sm` alone is 32px below `sm`), so a row's two round ends match.
64
+ */
65
+ const COMPOSER_SEND_BUTTON_CLASS = "bg-foreground text-background hover:bg-foreground/90 size-7 shrink-0 rounded-full";
66
+ /**
67
+ * A picker in the status row under the box (the chat's matter picker, the
68
+ * law home's scope and jurisdiction): quiet text with a hover surface, so
69
+ * the row stays subordinate to the box above it.
70
+ */
71
+ const COMPOSER_PICKER_TRIGGER_CLASS = "text-muted-foreground hover:text-foreground hover:bg-accent inline-flex min-w-0 shrink items-center gap-1 rounded-md px-1.5 py-0.5 text-2xs";
72
+ //#endregion
73
+ export { COMPOSER_BOX_ANONYMIZED_CLASS, COMPOSER_BOX_CLASS, COMPOSER_BOX_FOCUS_CLASS, COMPOSER_COMPACT_ROW_CLASS, COMPOSER_COMPACT_TEXT_CELL_CLASS, COMPOSER_CONTROL_BUTTON_SIZE, COMPOSER_LARGE_ACTION_ROW_CLASS, COMPOSER_LARGE_EDITOR_CLASS, COMPOSER_LARGE_TEXT_WELL_CLASS, COMPOSER_LEADING_GROUP_CLASS, COMPOSER_PICKER_TRIGGER_CLASS, COMPOSER_PLACEHOLDER_CLASS, COMPOSER_SEND_BUTTON_CLASS, COMPOSER_TEXT_CLASS };
@@ -1,75 +1,6 @@
1
+ import { COMPOSER_BOX_ANONYMIZED_CLASS, COMPOSER_BOX_CLASS, COMPOSER_BOX_FOCUS_CLASS, COMPOSER_COMPACT_ROW_CLASS, COMPOSER_COMPACT_TEXT_CELL_CLASS, COMPOSER_CONTROL_BUTTON_SIZE, COMPOSER_LARGE_ACTION_ROW_CLASS, COMPOSER_LARGE_EDITOR_CLASS, COMPOSER_LARGE_TEXT_WELL_CLASS, COMPOSER_LEADING_GROUP_CLASS, COMPOSER_PICKER_TRIGGER_CLASS, COMPOSER_PLACEHOLDER_CLASS, COMPOSER_SEND_BUTTON_CLASS, COMPOSER_TEXT_CLASS } from "./composer-tokens.js";
1
2
  import { ReactNode } from "react";
2
3
  //#region src/components/composer.d.ts
3
- /**
4
- * The tokens every composer box shares: the chat hero, the chat follow-up
5
- * bar, the docked bar over documents (inspector chat, file overlay,
6
- * Template Studio) and the law home's entry box all render one shell from
7
- * these, so they restyle together. A surface that needs the look imports
8
- * these rather than copying the classes; a copy is how the boxes drifted
9
- * apart the first time (44px / `rounded-lg` / 14px in the chat, 38px /
10
- * `rounded-2xl` / 13px in the inspector).
11
- */
12
- /** Shared responsive size for the two round controls flanking a composer. */
13
- export declare const COMPOSER_CONTROL_BUTTON_SIZE: "icon-sm";
14
- /** The bordered box: background, radius, border, colour transition. The
15
- * radius is the docked bar's original `rounded-2xl`: at the compact row's
16
- * stature it reads as a soft pill, which is the shape the composers were
17
- * meant to unify on. */
18
- export declare const COMPOSER_BOX_CLASS = "bg-background rounded-2xl border";
19
- /** The box's focus ring in its default (non-anonymized) treatment. */
20
- export declare const COMPOSER_BOX_FOCUS_CLASS = "focus-within:border-ring";
21
- /**
22
- * The box's "shield active" treatment when the next send is anonymized: a
23
- * blue ring replaces the default focus border (both together read as a
24
- * double ring on click).
25
- */
26
- export declare const COMPOSER_BOX_ANONYMIZED_CLASS = "ring-info/40 border-info/40 focus-within:border-info/60 shadow-[0_0_0_4px_rgb(from_var(--color-info)_r_g_b_/_0.08)] ring-1";
27
- /**
28
- * The compact (one-line) bar row: its stature, end alignment, control gap
29
- * and inset. The surface supplies the layout (`grid` for the chat bar's
30
- * three fixed columns, `flex` for the docked bar's variable leading
31
- * controls); the row grows with the editor.
32
- */
33
- export declare const COMPOSER_COMPACT_ROW_CLASS = "min-h-11 items-end gap-1 px-1.5 py-px";
34
- /**
35
- * The compact text cell: one `text-sm` line at `leading-5` plus the
36
- * vertical inset that makes a single line exactly as tall as the row's
37
- * inner height (44px row, 1px inset each side ⇒ 42px), so text and controls
38
- * share one centre. The editable element itself takes `min-h-0` so an empty
39
- * composer collapses to this one line and grows from there.
40
- */
41
- export declare const COMPOSER_COMPACT_TEXT_CELL_CLASS = "relative min-w-0 py-[11px]";
42
- /** Text stature of the editor and every placeholder painted over it. */
43
- export declare const COMPOSER_TEXT_CLASS = "text-sm leading-5";
44
- /**
45
- * The `large` (hero) text well: the padding around the editor. The editor's
46
- * own stature is `COMPOSER_LARGE_EDITOR_CLASS` (~3 lines of `text-sm` at
47
- * `leading-5`), applied on the editable element by each surface because the
48
- * chat editor targets its `.ProseMirror` node while a plain textarea takes
49
- * it directly.
50
- */
51
- export declare const COMPOSER_LARGE_TEXT_WELL_CLASS = "ps-3 pe-3 pt-2 pb-1";
52
- /** The `large` editable element's stature: three lines before it grows. */
53
- export declare const COMPOSER_LARGE_EDITOR_CLASS = "min-h-15";
54
- /** The placeholder painted over an empty editor, in either stature. */
55
- export declare const COMPOSER_PLACEHOLDER_CLASS = "text-foreground-placeholder pointer-events-none absolute truncate text-sm";
56
- /** The `large` action row under the text well: leading controls, trailing send. */
57
- export declare const COMPOSER_LARGE_ACTION_ROW_CLASS = "flex items-center justify-end gap-0.5 px-1.5 pb-1.5";
58
- /** The leading group of the action row (the (+) menu, or a scope control). */
59
- export declare const COMPOSER_LEADING_GROUP_CLASS = "flex min-w-0 items-center gap-0.5";
60
- /**
61
- * The round, foreground-filled primary control at the action row's end:
62
- * the chat's send/stop/retry button and the law home's submit. `size-7`
63
- * pins the circle to the (+) trigger's diameter at every breakpoint
64
- * (`icon-sm` alone is 32px below `sm`), so a row's two round ends match.
65
- */
66
- export declare const COMPOSER_SEND_BUTTON_CLASS = "bg-foreground text-background hover:bg-foreground/90 size-7 shrink-0 rounded-full";
67
- /**
68
- * A picker in the status row under the box (the chat's matter picker, the
69
- * law home's scope and jurisdiction): quiet text with a hover surface, so
70
- * the row stays subordinate to the box above it.
71
- */
72
- export declare const COMPOSER_PICKER_TRIGGER_CLASS = "text-muted-foreground hover:text-foreground hover:bg-accent inline-flex min-w-0 shrink items-center gap-1 rounded-md px-1.5 py-0.5 text-2xs";
73
4
  type ComposerStatusRowProps = {
74
5
  /** Left cluster: matter picker, web-search / anonymize toggles, ... */
75
6
  start?: ReactNode | undefined;
@@ -112,4 +43,5 @@ type ComposerPickerProps<Value extends string> = {
112
43
  * kind of control.
113
44
  */
114
45
  export declare const ComposerPicker: <Value extends string>({ ariaLabel, icon, onChange, options, value }: ComposerPickerProps<Value>) => import("react").JSX.Element;
115
- //#endregion
46
+ //#endregion
47
+ export { COMPOSER_BOX_ANONYMIZED_CLASS, COMPOSER_BOX_CLASS, COMPOSER_BOX_FOCUS_CLASS, COMPOSER_COMPACT_ROW_CLASS, COMPOSER_COMPACT_TEXT_CELL_CLASS, COMPOSER_CONTROL_BUTTON_SIZE, COMPOSER_LARGE_ACTION_ROW_CLASS, COMPOSER_LARGE_EDITOR_CLASS, COMPOSER_LARGE_TEXT_WELL_CLASS, COMPOSER_LEADING_GROUP_CLASS, COMPOSER_PICKER_TRIGGER_CLASS, COMPOSER_PLACEHOLDER_CLASS, COMPOSER_SEND_BUTTON_CLASS, COMPOSER_TEXT_CLASS };
@@ -2,79 +2,10 @@
2
2
  import { ChevronDownIcon } from "../icons.js";
3
3
  import { cn } from "../lib/utils.js";
4
4
  import { DropdownMenu as Menu, DropdownMenuContent as MenuPopup, DropdownMenuRadioGroup as MenuRadioGroup, DropdownMenuRadioItem as MenuRadioItem, DropdownMenuTrigger as MenuTrigger } from "./menu.js";
5
+ import { COMPOSER_BOX_ANONYMIZED_CLASS, COMPOSER_BOX_CLASS, COMPOSER_BOX_FOCUS_CLASS, COMPOSER_COMPACT_ROW_CLASS, COMPOSER_COMPACT_TEXT_CELL_CLASS, COMPOSER_CONTROL_BUTTON_SIZE, COMPOSER_LARGE_ACTION_ROW_CLASS, COMPOSER_LARGE_EDITOR_CLASS, COMPOSER_LARGE_TEXT_WELL_CLASS, COMPOSER_LEADING_GROUP_CLASS, COMPOSER_PICKER_TRIGGER_CLASS, COMPOSER_PLACEHOLDER_CLASS, COMPOSER_SEND_BUTTON_CLASS, COMPOSER_TEXT_CLASS } from "./composer-tokens.js";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  //#region src/components/composer.tsx
7
8
  /**
8
- * The tokens every composer box shares: the chat hero, the chat follow-up
9
- * bar, the docked bar over documents (inspector chat, file overlay,
10
- * Template Studio) and the law home's entry box all render one shell from
11
- * these, so they restyle together. A surface that needs the look imports
12
- * these rather than copying the classes; a copy is how the boxes drifted
13
- * apart the first time (44px / `rounded-lg` / 14px in the chat, 38px /
14
- * `rounded-2xl` / 13px in the inspector).
15
- */
16
- /** Shared responsive size for the two round controls flanking a composer. */
17
- const COMPOSER_CONTROL_BUTTON_SIZE = "icon-sm";
18
- /** The bordered box: background, radius, border, colour transition. The
19
- * radius is the docked bar's original `rounded-2xl`: at the compact row's
20
- * stature it reads as a soft pill, which is the shape the composers were
21
- * meant to unify on. */
22
- const COMPOSER_BOX_CLASS = "bg-background rounded-2xl border";
23
- /** The box's focus ring in its default (non-anonymized) treatment. */
24
- const COMPOSER_BOX_FOCUS_CLASS = "focus-within:border-ring";
25
- /**
26
- * The box's "shield active" treatment when the next send is anonymized: a
27
- * blue ring replaces the default focus border (both together read as a
28
- * double ring on click).
29
- */
30
- const COMPOSER_BOX_ANONYMIZED_CLASS = "ring-info/40 border-info/40 focus-within:border-info/60 shadow-[0_0_0_4px_rgb(from_var(--color-info)_r_g_b_/_0.08)] ring-1";
31
- /**
32
- * The compact (one-line) bar row: its stature, end alignment, control gap
33
- * and inset. The surface supplies the layout (`grid` for the chat bar's
34
- * three fixed columns, `flex` for the docked bar's variable leading
35
- * controls); the row grows with the editor.
36
- */
37
- const COMPOSER_COMPACT_ROW_CLASS = "min-h-11 items-end gap-1 px-1.5 py-px";
38
- /**
39
- * The compact text cell: one `text-sm` line at `leading-5` plus the
40
- * vertical inset that makes a single line exactly as tall as the row's
41
- * inner height (44px row, 1px inset each side ⇒ 42px), so text and controls
42
- * share one centre. The editable element itself takes `min-h-0` so an empty
43
- * composer collapses to this one line and grows from there.
44
- */
45
- const COMPOSER_COMPACT_TEXT_CELL_CLASS = "relative min-w-0 py-[11px]";
46
- /** Text stature of the editor and every placeholder painted over it. */
47
- const COMPOSER_TEXT_CLASS = "text-sm leading-5";
48
- /**
49
- * The `large` (hero) text well: the padding around the editor. The editor's
50
- * own stature is `COMPOSER_LARGE_EDITOR_CLASS` (~3 lines of `text-sm` at
51
- * `leading-5`), applied on the editable element by each surface because the
52
- * chat editor targets its `.ProseMirror` node while a plain textarea takes
53
- * it directly.
54
- */
55
- const COMPOSER_LARGE_TEXT_WELL_CLASS = "ps-3 pe-3 pt-2 pb-1";
56
- /** The `large` editable element's stature: three lines before it grows. */
57
- const COMPOSER_LARGE_EDITOR_CLASS = "min-h-15";
58
- /** The placeholder painted over an empty editor, in either stature. */
59
- const COMPOSER_PLACEHOLDER_CLASS = "text-foreground-placeholder pointer-events-none absolute truncate text-sm";
60
- /** The `large` action row under the text well: leading controls, trailing send. */
61
- const COMPOSER_LARGE_ACTION_ROW_CLASS = "flex items-center justify-end gap-0.5 px-1.5 pb-1.5";
62
- /** The leading group of the action row (the (+) menu, or a scope control). */
63
- const COMPOSER_LEADING_GROUP_CLASS = "flex min-w-0 items-center gap-0.5";
64
- /**
65
- * The round, foreground-filled primary control at the action row's end:
66
- * the chat's send/stop/retry button and the law home's submit. `size-7`
67
- * pins the circle to the (+) trigger's diameter at every breakpoint
68
- * (`icon-sm` alone is 32px below `sm`), so a row's two round ends match.
69
- */
70
- const COMPOSER_SEND_BUTTON_CLASS = "bg-foreground text-background hover:bg-foreground/90 size-7 shrink-0 rounded-full";
71
- /**
72
- * A picker in the status row under the box (the chat's matter picker, the
73
- * law home's scope and jurisdiction): quiet text with a hover surface, so
74
- * the row stays subordinate to the box above it.
75
- */
76
- const COMPOSER_PICKER_TRIGGER_CLASS = "text-muted-foreground hover:text-foreground hover:bg-accent inline-flex min-w-0 shrink items-center gap-1 rounded-md px-1.5 py-0.5 text-2xs";
77
- /**
78
9
  * The slim status row rendered beneath a composer box: a `text-xs` row with
79
10
  * a start cluster and an end slot pinned to the far edge. Shared by every
80
11
  * surface so the shell can never drift. Renders nothing when both slots are
@@ -1,6 +1,6 @@
1
1
  import { Button } from "./button.js";
2
- import { CopyToClipboardIcon } from "../icons.js";
3
2
  import { ComponentProps } from "react";
3
+ import { CopyToClipboardIcon } from "../icons.js";
4
4
  //#region src/components/copy-button.d.ts
5
5
  export declare const COPIED_RESET_MS = 1500;
6
6
  type CopyButtonProps = Omit<ComponentProps<typeof Button>, "children" | "onClick"> & {
@@ -1,5 +1,5 @@
1
- import { OverlayLayer } from "../lib/overlay-layer.js";
2
1
  import { DatePickerMode } from "./date-picker-popover.logic.js";
2
+ import { OverlayLayer } from "../lib/overlay-layer.js";
3
3
  //#region src/components/date-picker-popover.d.ts
4
4
  /**
5
5
  * `compact` keeps the dense 32px day cells everywhere. `touch` grows day,
@@ -1,5 +1,5 @@
1
- import { InputProps } from "./input.js";
2
1
  import * as React$1 from "react";
2
+ import { InputProps } from "./input.js";
3
3
  //#region src/components/destructive-action-confirmation.d.ts
4
4
  type DestructiveActionConfirmationProps = Omit<InputProps, "onChange" | "type" | "value"> & {
5
5
  confirmation: string;
@@ -1,7 +1,7 @@
1
- import { OverlayLayer } from "../lib/overlay-layer.js";
2
- import { DialogFormState } from "./dialog-form-state.js";
3
1
  import * as React$1 from "react";
4
2
  import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
3
+ import { DialogFormState } from "./dialog-form-state.js";
4
+ import { OverlayLayer } from "../lib/overlay-layer.js";
5
5
  //#region src/components/dialog.d.ts
6
6
  declare const DialogCreateHandle: typeof Dialog$1.createHandle;
7
7
  type DialogLabels = {
@@ -2,7 +2,7 @@ import { FileTextIcon } from "../icons.js";
2
2
  import { cn } from "../lib/utils.js";
3
3
  import { Tooltip, TooltipContent as TooltipPopup, TooltipTrigger } from "./tooltip.js";
4
4
  import { CourtBadge } from "./court-badge.js";
5
- import { COURT_TIER_WEIGHT, statuteIdentityLabels } from "./document-identity-badge.logic.js";
5
+ import { COURT_TIER_WEIGHT, caseNumberIdentityLabels, statuteIdentityLabels } from "./document-identity-badge.logic.js";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { panic } from "better-result";
8
8
  //#region src/components/document-identity-badge.tsx
@@ -18,21 +18,11 @@ function documentIdentityMark(identity, size) {
18
18
  switch (identity.kind) {
19
19
  case "statute": {
20
20
  const labels = statuteIdentityLabels(identity);
21
- if (labels === null) return unknownDocumentMark();
22
- return /* @__PURE__ */ jsxs("span", {
23
- className: cn("@container/document-identity inline-flex max-w-full shrink-0 items-center justify-center font-mono leading-4 font-semibold tabular-nums", labels.short.length > 7 ? "text-[9px]" : "text-[10px]"),
24
- style: { width: `${labels.long.length + .25}ch` },
25
- "data-slot": "document-identity-badge",
26
- "data-kind": "statute",
27
- dir: "ltr",
28
- children: [/* @__PURE__ */ jsx("bdi", {
29
- className: statuteLabelClasses(labels.long.length).short,
30
- children: labels.short
31
- }), /* @__PURE__ */ jsx("bdi", {
32
- className: statuteLabelClasses(labels.long.length).long,
33
- children: labels.long
34
- })]
35
- });
21
+ return labels === null ? unknownDocumentMark() : referenceLabelMark(labels, "statute");
22
+ }
23
+ case "caseNumber": {
24
+ const labels = caseNumberIdentityLabels(identity);
25
+ return labels === null ? unknownDocumentMark() : referenceLabelMark(labels, "caseNumber");
36
26
  }
37
27
  case "decision": {
38
28
  const abbreviation = identity.courtAbbreviation?.trim();
@@ -53,6 +43,30 @@ function documentIdentityMark(identity, size) {
53
43
  default: return panic("Unhandled document identity");
54
44
  }
55
45
  }
46
+ /**
47
+ * A number standing for its document: a statute's `165/12`, a decision's
48
+ * `C-359/25`. Container queries compare available space with the full label
49
+ * in the same monospace units, so no observer or per-row state is needed; a
50
+ * label longer than its slot even in the short form truncates rather than
51
+ * spilling over its neighbour.
52
+ */
53
+ function referenceLabelMark(labels, kind) {
54
+ const classes = statuteLabelClasses(labels.long.length);
55
+ return /* @__PURE__ */ jsxs("span", {
56
+ className: cn("@container/document-identity inline-flex max-w-full shrink-0 items-center justify-center font-mono leading-4 font-semibold tabular-nums", labels.short.length > 7 ? "text-[9px]" : "text-[10px]"),
57
+ style: { width: `${labels.long.length + .25}ch` },
58
+ "data-slot": "document-identity-badge",
59
+ "data-kind": kind,
60
+ dir: "ltr",
61
+ children: [/* @__PURE__ */ jsx("bdi", {
62
+ className: cn("min-w-0 truncate", classes.short),
63
+ children: labels.short
64
+ }), /* @__PURE__ */ jsx("bdi", {
65
+ className: cn("min-w-0 truncate", classes.long),
66
+ children: labels.long
67
+ })]
68
+ });
69
+ }
56
70
  function unknownDocumentMark() {
57
71
  return /* @__PURE__ */ jsx(FileTextIcon, {
58
72
  "aria-hidden": "true",
@@ -13,13 +13,32 @@ export type DocumentIdentity = {
13
13
  kind: "decision";
14
14
  courtAbbreviation: string | null | undefined;
15
15
  courtTier?: keyof typeof COURT_TIER_WEIGHT | undefined;
16
+ } |
17
+ /**
18
+ * A decision named by its own case number, where a court chip would not
19
+ * tell several open decisions apart (one court's tabs side by side).
20
+ */
21
+ {
22
+ kind: "caseNumber";
23
+ caseNumber: string | null | undefined;
16
24
  } | {
17
25
  kind: "unknown";
18
26
  };
19
- export declare const statuteIdentityLabels: ({ number, year }: Extract<DocumentIdentity, {
20
- kind: "statute";
21
- }>) => {
27
+ /** A reference label in its narrow and its full form. */
28
+ export type IdentityLabels = {
22
29
  short: string;
23
30
  long: string;
24
- } | null;
31
+ };
32
+ export declare const statuteIdentityLabels: ({ number, year }: Extract<DocumentIdentity, {
33
+ kind: "statute";
34
+ }>) => IdentityLabels | null;
35
+ /**
36
+ * A case number in the two forms a statute number takes: the full one, and
37
+ * one whose closing four-digit year is cut to two, the way `165/2012` reads
38
+ * `165/12`. A number already printed with a two-digit year (`C-359/25`) is
39
+ * its own short form.
40
+ */
41
+ export declare const caseNumberIdentityLabels: ({ caseNumber }: Extract<DocumentIdentity, {
42
+ kind: "caseNumber";
43
+ }>) => IdentityLabels | null;
25
44
  //#endregion
@@ -21,5 +21,21 @@ const statuteIdentityLabels = ({ number, year }) => {
21
21
  long: `${ordinal}/${fullYear}`
22
22
  };
23
23
  };
24
+ /** A four-digit year closing a case number: `1234/2019`, `C-1/2004`. */
25
+ const TRAILING_FULL_YEAR = /\/\d{2}(\d{2})$/u;
26
+ /**
27
+ * A case number in the two forms a statute number takes: the full one, and
28
+ * one whose closing four-digit year is cut to two, the way `165/2012` reads
29
+ * `165/12`. A number already printed with a two-digit year (`C-359/25`) is
30
+ * its own short form.
31
+ */
32
+ const caseNumberIdentityLabels = ({ caseNumber }) => {
33
+ const long = caseNumber?.trim().replaceAll(/\s+/gu, " ") ?? "";
34
+ if (long === "") return null;
35
+ return {
36
+ short: long.replace(TRAILING_FULL_YEAR, "/$1"),
37
+ long
38
+ };
39
+ };
24
40
  //#endregion
25
- export { COURT_TIER_WEIGHT, statuteIdentityLabels };
41
+ export { COURT_TIER_WEIGHT, caseNumberIdentityLabels, statuteIdentityLabels };
@@ -1,6 +1,6 @@
1
+ import * as React$1 from "react";
1
2
  import { InputProps } from "./input.js";
2
3
  import { TextareaProps } from "./textarea.js";
3
- import * as React$1 from "react";
4
4
  import { VariantProps } from "class-variance-authority";
5
5
  //#region src/components/input-group.d.ts
6
6
  declare const InputGroup: ({ className, ...props }: React$1.ComponentProps<"div">) => React$1.JSX.Element;
@@ -1,5 +1,5 @@
1
- import { ControlSize } from "../lib/control-size.js";
2
1
  import * as React$1 from "react";
2
+ import { ControlSize } from "../lib/control-size.js";
3
3
  import { Input as Input$1 } from "@base-ui/react/input";
4
4
  //#region src/components/input.d.ts
5
5
  type InputProps = Omit<Input$1.Props & React$1.RefAttributes<HTMLInputElement>, "size" | "style" | "type"> & {
@@ -1,6 +1,6 @@
1
1
  import * as React$1 from "react";
2
- import { useRender } from "@base-ui/react/use-render";
3
2
  import { VariantProps } from "class-variance-authority";
3
+ import { useRender } from "@base-ui/react/use-render";
4
4
  //#region src/components/list.d.ts
5
5
  /**
6
6
  * Grouped list: a titled section holding one surface of hairline-divided
@@ -1,5 +1,5 @@
1
- import { Button } from "./button.js";
2
1
  import * as React$1 from "react";
2
+ import { Button } from "./button.js";
3
3
  import { useRender } from "@base-ui/react/use-render";
4
4
  //#region src/components/pagination.d.ts
5
5
  declare const Pagination: ({ className, ...props }: React$1.ComponentProps<"nav">) => React$1.JSX.Element;
@@ -1,6 +1,6 @@
1
- import { OverlayLayer } from "../lib/overlay-layer.js";
2
1
  import * as React$1 from "react";
3
2
  import { ComponentProps } from "react";
3
+ import { OverlayLayer } from "../lib/overlay-layer.js";
4
4
  import { Popover as Popover$1 } from "@base-ui/react/popover";
5
5
  //#region src/components/popover.d.ts
6
6
  declare const PopoverCreateHandle: typeof Popover$1.createHandle;