terminoir 0.4.0 → 0.5.1

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 (98) hide show
  1. package/README.md +38 -28
  2. package/css/components.css +62 -0
  3. package/css/shell.css +32 -1
  4. package/dist/components/AccentSwatches.svelte +1 -1
  5. package/dist/components/AppShell.svelte +33 -5
  6. package/dist/components/AppShell.svelte.d.ts +10 -1
  7. package/dist/components/AppShellNavLink.svelte +2 -4
  8. package/dist/components/Button.svelte +32 -14
  9. package/dist/components/Button.svelte.d.ts +2 -0
  10. package/dist/components/CalendarGrid.svelte +260 -0
  11. package/dist/components/CalendarGrid.svelte.d.ts +12 -0
  12. package/dist/components/CanvasStage.svelte +81 -0
  13. package/dist/components/CanvasStage.svelte.d.ts +19 -0
  14. package/dist/components/Centered.svelte +36 -0
  15. package/dist/components/Centered.svelte.d.ts +10 -0
  16. package/dist/components/Checkbox.svelte +64 -12
  17. package/dist/components/Checkbox.svelte.d.ts +5 -0
  18. package/dist/components/Chip.svelte +90 -2
  19. package/dist/components/Chip.svelte.d.ts +8 -0
  20. package/dist/components/CommandPalette.svelte +178 -97
  21. package/dist/components/CommandPalette.svelte.d.ts +15 -8
  22. package/dist/components/ContextMenu.svelte +68 -0
  23. package/dist/components/ContextMenu.svelte.d.ts +12 -0
  24. package/dist/components/DataTable.svelte +139 -0
  25. package/dist/components/DataTable.svelte.d.ts +39 -0
  26. package/dist/components/DescriptionList.svelte +41 -0
  27. package/dist/components/DescriptionList.svelte.d.ts +8 -0
  28. package/dist/components/Dialog.svelte +17 -8
  29. package/dist/components/Disclosure.svelte +55 -0
  30. package/dist/components/Disclosure.svelte.d.ts +10 -0
  31. package/dist/components/DocumentViewer.svelte +105 -0
  32. package/dist/components/DocumentViewer.svelte.d.ts +23 -0
  33. package/dist/components/Drawer.svelte +119 -0
  34. package/dist/components/Drawer.svelte.d.ts +16 -0
  35. package/dist/components/DropdownMenu.svelte +46 -62
  36. package/dist/components/DropdownMenu.svelte.d.ts +7 -6
  37. package/dist/components/FieldMessage.svelte +9 -0
  38. package/dist/components/FieldMessage.svelte.d.ts +8 -0
  39. package/dist/components/FileButton.svelte +44 -0
  40. package/dist/components/FileButton.svelte.d.ts +16 -0
  41. package/dist/components/FormRow.svelte +62 -0
  42. package/dist/components/FormRow.svelte.d.ts +13 -0
  43. package/dist/components/IconField.svelte +80 -5
  44. package/dist/components/IconField.svelte.d.ts +2 -0
  45. package/dist/components/Inline.svelte +52 -0
  46. package/dist/components/Inline.svelte.d.ts +16 -0
  47. package/dist/components/Input.svelte +23 -3
  48. package/dist/components/Input.svelte.d.ts +9 -0
  49. package/dist/components/List.svelte +42 -0
  50. package/dist/components/List.svelte.d.ts +13 -0
  51. package/dist/components/ListItem.svelte +114 -0
  52. package/dist/components/ListItem.svelte.d.ts +17 -0
  53. package/dist/components/MenuItems.svelte +44 -0
  54. package/dist/components/MenuItems.svelte.d.ts +8 -0
  55. package/dist/components/NavSection.svelte +45 -0
  56. package/dist/components/NavSection.svelte.d.ts +12 -0
  57. package/dist/components/Page.svelte +53 -0
  58. package/dist/components/Page.svelte.d.ts +12 -0
  59. package/dist/components/PageHeader.svelte +91 -0
  60. package/dist/components/PageHeader.svelte.d.ts +15 -0
  61. package/dist/components/Prose.svelte +33 -0
  62. package/dist/components/Prose.svelte.d.ts +8 -0
  63. package/dist/components/RadioCards.svelte +68 -0
  64. package/dist/components/RadioCards.svelte.d.ts +11 -0
  65. package/dist/components/SearchPicker.svelte +171 -0
  66. package/dist/components/SearchPicker.svelte.d.ts +19 -0
  67. package/dist/components/Section.svelte +71 -0
  68. package/dist/components/Section.svelte.d.ts +12 -0
  69. package/dist/components/SegmentedControl.svelte +63 -0
  70. package/dist/components/SegmentedControl.svelte.d.ts +12 -0
  71. package/dist/components/Select.svelte +22 -4
  72. package/dist/components/Select.svelte.d.ts +9 -1
  73. package/dist/components/Spacer.svelte +6 -0
  74. package/dist/components/Spacer.svelte.d.ts +26 -0
  75. package/dist/components/Stack.svelte +37 -0
  76. package/dist/components/Stack.svelte.d.ts +12 -0
  77. package/dist/components/Switch.svelte +6 -2
  78. package/dist/components/Switch.svelte.d.ts +2 -0
  79. package/dist/components/Tabs.svelte +6 -4
  80. package/dist/components/Text.svelte +68 -0
  81. package/dist/components/Text.svelte.d.ts +15 -0
  82. package/dist/components/Textarea.svelte +19 -3
  83. package/dist/components/Textarea.svelte.d.ts +6 -0
  84. package/dist/components/TitleInput.svelte +62 -0
  85. package/dist/components/TitleInput.svelte.d.ts +10 -0
  86. package/dist/index.d.ts +35 -2
  87. package/dist/index.js +31 -0
  88. package/dist/utils/calendar.d.ts +48 -0
  89. package/dist/utils/calendar.js +105 -0
  90. package/dist/utils/commands.d.ts +22 -0
  91. package/dist/utils/commands.js +17 -0
  92. package/dist/utils/componentTypes.d.ts +41 -0
  93. package/dist/utils/componentTypes.js +1 -0
  94. package/dist/utils/listNav.d.ts +2 -0
  95. package/dist/utils/listNav.js +8 -0
  96. package/dist/utils/menu.d.ts +10 -0
  97. package/dist/utils/menu.js +1 -0
  98. package/package.json +5 -3
@@ -1,8 +1,14 @@
1
1
  <script lang="ts">
2
+ import type { Snippet } from 'svelte';
2
3
  import { cn } from '../utils/cn.js';
4
+ import FieldMessage from './FieldMessage.svelte';
3
5
 
4
6
  let {
5
7
  label,
8
+ hideLabel = false,
9
+ quiet = false,
10
+ hint,
11
+ error,
6
12
  id,
7
13
  value = $bindable(''),
8
14
  disabled = false,
@@ -11,25 +17,37 @@
11
17
  ...rest
12
18
  }: {
13
19
  label: string;
20
+ /** Keep the label for screen readers only (compact rows, toolbars). */
21
+ hideLabel?: boolean;
22
+ /** Borderless until hovered or focused, for inline editing (property rows). */
23
+ quiet?: boolean;
24
+ hint?: string;
25
+ error?: string;
14
26
  id?: string;
15
27
  value?: string;
16
28
  disabled?: boolean;
17
29
  class?: string;
18
- children?: import('svelte').Snippet;
30
+ /** `<option>` elements. */
31
+ children?: Snippet;
19
32
  } & Record<string, unknown> = $props();
20
33
 
21
- const selectId = $derived(id ?? `terminoir-select-${Math.random().toString(36).slice(2, 8)}`);
34
+ const fallbackId = $props.id();
35
+ const selectId = $derived(id ?? fallbackId);
36
+ const messageId = $derived(`${selectId}-message`);
22
37
  </script>
23
38
 
24
- <div class={cn('terminoir-field', className)}>
25
- <label class="terminoir-field__label" for={selectId}>{label}</label>
39
+ <div class={cn('terminoir-field', quiet && 'terminoir-field--quiet', className)}>
40
+ <label class={cn('terminoir-field__label', hideLabel && 'terminoir-sr-only')} for={selectId}>{label}</label>
26
41
  <select
27
42
  id={selectId}
28
43
  class="terminoir-select terminoir-focusable"
29
44
  bind:value
30
45
  {disabled}
46
+ aria-invalid={error ? true : undefined}
47
+ aria-describedby={error || hint ? messageId : undefined}
31
48
  {...rest}
32
49
  >
33
50
  {@render children?.()}
34
51
  </select>
52
+ <FieldMessage id={messageId} {hint} {error} />
35
53
  </div>
@@ -1,10 +1,18 @@
1
+ import type { Snippet } from 'svelte';
1
2
  type $$ComponentProps = {
2
3
  label: string;
4
+ /** Keep the label for screen readers only (compact rows, toolbars). */
5
+ hideLabel?: boolean;
6
+ /** Borderless until hovered or focused, for inline editing (property rows). */
7
+ quiet?: boolean;
8
+ hint?: string;
9
+ error?: string;
3
10
  id?: string;
4
11
  value?: string;
5
12
  disabled?: boolean;
6
13
  class?: string;
7
- children?: import('svelte').Snippet;
14
+ /** `<option>` elements. */
15
+ children?: Snippet;
8
16
  } & Record<string, unknown>;
9
17
  declare const Select: import("svelte").Component<$$ComponentProps, {}, "value">;
10
18
  type Select = ReturnType<typeof Select>;
@@ -0,0 +1,6 @@
1
+ <!-- Fills free space in a flex column or row, e.g. to pin a footer link to the bottom of a sidebar. -->
2
+ <div class="terminoir-spacer" aria-hidden="true"></div>
3
+
4
+ <style>
5
+ .terminoir-spacer { flex: 1 1 auto; }
6
+ </style>
@@ -0,0 +1,26 @@
1
+ export default Spacer;
2
+ type Spacer = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const Spacer: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -0,0 +1,37 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { cn } from '../utils/cn.js';
4
+
5
+ type Gap = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12;
6
+
7
+ let {
8
+ gap = 4,
9
+ align = 'stretch',
10
+ class: className = '',
11
+ children,
12
+ ...rest
13
+ }: {
14
+ /** Spacing between children, as a `--space-*` step. */
15
+ gap?: Gap;
16
+ align?: 'stretch' | 'start' | 'center' | 'end';
17
+ class?: string;
18
+ children?: Snippet;
19
+ } & Record<string, unknown> = $props();
20
+ </script>
21
+
22
+ <div
23
+ class={cn('terminoir-stack', className)}
24
+ style:gap={`var(--space-${gap})`}
25
+ style:align-items={align === 'stretch' ? 'stretch' : align === 'center' ? 'center' : `flex-${align}`}
26
+ {...rest}
27
+ >
28
+ {@render children?.()}
29
+ </div>
30
+
31
+ <style>
32
+ .terminoir-stack {
33
+ display: flex;
34
+ flex-direction: column;
35
+ min-width: 0;
36
+ }
37
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from 'svelte';
2
+ type Gap = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12;
3
+ type $$ComponentProps = {
4
+ /** Spacing between children, as a `--space-*` step. */
5
+ gap?: Gap;
6
+ align?: 'stretch' | 'start' | 'center' | 'end';
7
+ class?: string;
8
+ children?: Snippet;
9
+ } & Record<string, unknown>;
10
+ declare const Stack: import("svelte").Component<$$ComponentProps, {}, "">;
11
+ type Stack = ReturnType<typeof Stack>;
12
+ export default Stack;
@@ -3,6 +3,7 @@
3
3
 
4
4
  let {
5
5
  label,
6
+ hideLabel = false,
6
7
  checked = $bindable(false),
7
8
  disabled = false,
8
9
  class: className = '',
@@ -10,17 +11,20 @@
10
11
  ...rest
11
12
  }: {
12
13
  label: string;
14
+ /** Keep the label for screen readers only (e.g. a switch inside a list row). */
15
+ hideLabel?: boolean;
13
16
  checked?: boolean;
14
17
  disabled?: boolean;
15
18
  class?: string;
16
19
  id?: string;
17
20
  } & Record<string, unknown> = $props();
18
21
 
19
- const inputId = $derived(id ?? `terminoir-switch-${Math.random().toString(36).slice(2, 8)}`);
22
+ const fallbackId = $props.id();
23
+ const inputId = $derived(id ?? fallbackId);
20
24
  </script>
21
25
 
22
26
  <label class={cn('terminoir-switch', className)}>
23
- <span class="terminoir-field__label">{label}</span>
27
+ <span class={cn('terminoir-field__label', hideLabel && 'terminoir-sr-only')}>{label}</span>
24
28
  <input
25
29
  id={inputId}
26
30
  type="checkbox"
@@ -1,5 +1,7 @@
1
1
  type $$ComponentProps = {
2
2
  label: string;
3
+ /** Keep the label for screen readers only (e.g. a switch inside a list row). */
4
+ hideLabel?: boolean;
3
5
  checked?: boolean;
4
6
  disabled?: boolean;
5
7
  class?: string;
@@ -14,6 +14,8 @@
14
14
  children?: Snippet;
15
15
  } = $props();
16
16
 
17
+ const uid = $props.id();
18
+
17
19
  $effect.pre(() => {
18
20
  if (!value && tabs[0]) value = tabs[0].id;
19
21
  });
@@ -25,9 +27,9 @@
25
27
  <button
26
28
  type="button"
27
29
  role="tab"
28
- id={`tab-${tab.id}`}
30
+ id={`${uid}-tab-${tab.id}`}
29
31
  aria-selected={value === tab.id}
30
- aria-controls={`panel-${tab.id}`}
32
+ aria-controls={`${uid}-panel-${tab.id}`}
31
33
  class="terminoir-tabs__trigger terminoir-focusable"
32
34
  onclick={() => (value = tab.id)}
33
35
  >
@@ -38,8 +40,8 @@
38
40
  {#each tabs as tab (tab.id)}
39
41
  <div
40
42
  role="tabpanel"
41
- id={`panel-${tab.id}`}
42
- aria-labelledby={`tab-${tab.id}`}
43
+ id={`${uid}-panel-${tab.id}`}
44
+ aria-labelledby={`${uid}-tab-${tab.id}`}
43
45
  hidden={value !== tab.id}
44
46
  class="terminoir-tabs__panel"
45
47
  >
@@ -0,0 +1,68 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { cn } from '../utils/cn.js';
4
+
5
+ let {
6
+ as = 'p',
7
+ tone = 'default',
8
+ size = 'md',
9
+ weight = 'normal',
10
+ truncate = false,
11
+ mono = false,
12
+ class: className = '',
13
+ children,
14
+ ...rest
15
+ }: {
16
+ as?: 'p' | 'span' | 'div' | 'small';
17
+ tone?: 'default' | 'muted' | 'danger' | 'success' | 'warning';
18
+ size?: 'xs' | 'sm' | 'md' | 'lg';
19
+ weight?: 'normal' | 'medium' | 'semibold';
20
+ /** Single line with an ellipsis. */
21
+ truncate?: boolean;
22
+ mono?: boolean;
23
+ class?: string;
24
+ children?: Snippet;
25
+ } & Record<string, unknown> = $props();
26
+ </script>
27
+
28
+ <svelte:element
29
+ this={as}
30
+ class={cn(
31
+ 'terminoir-text',
32
+ `terminoir-text--${tone}`,
33
+ `terminoir-text--${size}`,
34
+ `terminoir-text--${weight}`,
35
+ truncate && 'terminoir-text--truncate',
36
+ mono && 'terminoir-text--mono',
37
+ className,
38
+ )}
39
+ {...rest}
40
+ >
41
+ {@render children?.()}
42
+ </svelte:element>
43
+
44
+ <style>
45
+ .terminoir-text {
46
+ margin: 0;
47
+ min-width: 0;
48
+ line-height: 1.5;
49
+ }
50
+ .terminoir-text--default { color: var(--foreground); }
51
+ .terminoir-text--muted { color: var(--muted-foreground); }
52
+ .terminoir-text--danger { color: var(--destructive); }
53
+ .terminoir-text--success { color: var(--status-done); }
54
+ .terminoir-text--warning { color: var(--status-today); }
55
+ .terminoir-text--xs { font-size: 0.75rem; }
56
+ .terminoir-text--sm { font-size: 0.8125rem; }
57
+ .terminoir-text--md { font-size: 0.875rem; }
58
+ .terminoir-text--lg { font-size: 1rem; }
59
+ .terminoir-text--normal { font-weight: 400; }
60
+ .terminoir-text--medium { font-weight: 500; }
61
+ .terminoir-text--semibold { font-weight: 600; }
62
+ .terminoir-text--truncate {
63
+ overflow: hidden;
64
+ text-overflow: ellipsis;
65
+ white-space: nowrap;
66
+ }
67
+ .terminoir-text--mono { font-family: var(--font-mono); }
68
+ </style>
@@ -0,0 +1,15 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ as?: 'p' | 'span' | 'div' | 'small';
4
+ tone?: 'default' | 'muted' | 'danger' | 'success' | 'warning';
5
+ size?: 'xs' | 'sm' | 'md' | 'lg';
6
+ weight?: 'normal' | 'medium' | 'semibold';
7
+ /** Single line with an ellipsis. */
8
+ truncate?: boolean;
9
+ mono?: boolean;
10
+ class?: string;
11
+ children?: Snippet;
12
+ } & Record<string, unknown>;
13
+ declare const Text: import("svelte").Component<$$ComponentProps, {}, "">;
14
+ type Text = ReturnType<typeof Text>;
15
+ export default Text;
@@ -1,8 +1,13 @@
1
1
  <script lang="ts">
2
2
  import { cn } from '../utils/cn.js';
3
+ import FieldMessage from './FieldMessage.svelte';
3
4
 
4
5
  let {
5
6
  label,
7
+ hideLabel = false,
8
+ quiet = false,
9
+ hint,
10
+ error,
6
11
  id,
7
12
  value = $bindable(''),
8
13
  rows = 4,
@@ -12,6 +17,12 @@
12
17
  ...rest
13
18
  }: {
14
19
  label: string;
20
+ /** Keep the label for screen readers only. */
21
+ hideLabel?: boolean;
22
+ /** Borderless until hovered or focused, for inline editing (property rows). */
23
+ quiet?: boolean;
24
+ hint?: string;
25
+ error?: string;
15
26
  id?: string;
16
27
  value?: string;
17
28
  rows?: number;
@@ -20,11 +31,13 @@
20
31
  class?: string;
21
32
  } & Record<string, unknown> = $props();
22
33
 
23
- const inputId = $derived(id ?? `terminoir-textarea-${Math.random().toString(36).slice(2, 8)}`);
34
+ const fallbackId = $props.id();
35
+ const inputId = $derived(id ?? fallbackId);
36
+ const messageId = $derived(`${inputId}-message`);
24
37
  </script>
25
38
 
26
- <div class={cn('terminoir-field', className)}>
27
- <label class="terminoir-field__label" for={inputId}>{label}</label>
39
+ <div class={cn('terminoir-field', quiet && 'terminoir-field--quiet', className)}>
40
+ <label class={cn('terminoir-field__label', hideLabel && 'terminoir-sr-only')} for={inputId}>{label}</label>
28
41
  <textarea
29
42
  id={inputId}
30
43
  class="terminoir-textarea terminoir-focusable"
@@ -32,6 +45,9 @@
32
45
  {rows}
33
46
  {placeholder}
34
47
  {disabled}
48
+ aria-invalid={error ? true : undefined}
49
+ aria-describedby={error || hint ? messageId : undefined}
35
50
  {...rest}
36
51
  ></textarea>
52
+ <FieldMessage id={messageId} {hint} {error} />
37
53
  </div>
@@ -1,5 +1,11 @@
1
1
  type $$ComponentProps = {
2
2
  label: string;
3
+ /** Keep the label for screen readers only. */
4
+ hideLabel?: boolean;
5
+ /** Borderless until hovered or focused, for inline editing (property rows). */
6
+ quiet?: boolean;
7
+ hint?: string;
8
+ error?: string;
3
9
  id?: string;
4
10
  value?: string;
5
11
  rows?: number;
@@ -0,0 +1,62 @@
1
+ <script lang="ts">
2
+ import { cn } from '../utils/cn.js';
3
+
4
+ let {
5
+ label,
6
+ value = $bindable(''),
7
+ placeholder = 'Untitled',
8
+ class: className = '',
9
+ ...rest
10
+ }: {
11
+ /** Accessible name; not shown (the title itself is the heading). */
12
+ label: string;
13
+ value?: string;
14
+ placeholder?: string;
15
+ class?: string;
16
+ } & Record<string, unknown> = $props();
17
+
18
+ /** Titles are one line: Enter commits instead of inserting a newline. */
19
+ function onkeydown(event: KeyboardEvent) {
20
+ if (event.key === 'Enter') {
21
+ event.preventDefault();
22
+ (event.currentTarget as HTMLTextAreaElement).blur();
23
+ }
24
+ }
25
+ </script>
26
+
27
+ <textarea
28
+ class={cn('terminoir-title-input terminoir-focusable', className)}
29
+ aria-label={label}
30
+ rows="1"
31
+ bind:value
32
+ {placeholder}
33
+ {onkeydown}
34
+ {...rest}
35
+ ></textarea>
36
+
37
+ <style>
38
+ .terminoir-title-input {
39
+ width: 100%;
40
+ margin: 0;
41
+ padding: 0.1rem 0.25rem;
42
+ margin-inline: -0.25rem;
43
+ border: 1px solid transparent;
44
+ border-radius: var(--radius-control);
45
+ background: transparent;
46
+ color: var(--foreground);
47
+ font: inherit;
48
+ font-size: 1.75rem;
49
+ font-weight: 600;
50
+ line-height: 1.25;
51
+ letter-spacing: -0.01em;
52
+ resize: none;
53
+ field-sizing: content;
54
+ overflow: hidden;
55
+ }
56
+ .terminoir-title-input:hover { border-color: color-mix(in srgb, var(--foreground) 10%, transparent); }
57
+ .terminoir-title-input:focus-visible { outline: none; border-color: var(--ring); }
58
+ .terminoir-title-input::placeholder { color: var(--muted-foreground); }
59
+ @media (max-width: 700px) {
60
+ .terminoir-title-input { font-size: 1.375rem; }
61
+ }
62
+ </style>
@@ -0,0 +1,10 @@
1
+ type $$ComponentProps = {
2
+ /** Accessible name; not shown (the title itself is the heading). */
3
+ label: string;
4
+ value?: string;
5
+ placeholder?: string;
6
+ class?: string;
7
+ } & Record<string, unknown>;
8
+ declare const TitleInput: import("svelte").Component<$$ComponentProps, {}, "value">;
9
+ type TitleInput = ReturnType<typeof TitleInput>;
10
+ export default TitleInput;
package/dist/index.d.ts CHANGED
@@ -17,10 +17,10 @@ export { default as CardGrid } from './components/CardGrid.svelte';
17
17
  export { default as Checkbox } from './components/Checkbox.svelte';
18
18
  export { default as Chip } from './components/Chip.svelte';
19
19
  export { default as CommandPalette } from './components/CommandPalette.svelte';
20
- export type { CommandItem } from './components/CommandPalette.svelte';
20
+ export type { CommandItem } from './utils/commands.js';
21
21
  export { default as Dialog } from './components/Dialog.svelte';
22
22
  export { default as DropdownMenu } from './components/DropdownMenu.svelte';
23
- export type { MenuItem } from './components/DropdownMenu.svelte';
23
+ export type { MenuItem } from './utils/menu.js';
24
24
  export { default as EmptyState } from './components/EmptyState.svelte';
25
25
  export { default as FontPicker } from './components/FontPicker.svelte';
26
26
  export { default as NavIcon } from './components/NavIcon.svelte';
@@ -38,3 +38,36 @@ export { default as Tabs } from './components/Tabs.svelte';
38
38
  export { default as Textarea } from './components/Textarea.svelte';
39
39
  export { default as Toaster } from './components/Toaster.svelte';
40
40
  export { default as Tooltip } from './components/Tooltip.svelte';
41
+ export { default as Page } from './components/Page.svelte';
42
+ export { default as PageHeader } from './components/PageHeader.svelte';
43
+ export { default as Section } from './components/Section.svelte';
44
+ export { default as Stack } from './components/Stack.svelte';
45
+ export { default as Inline } from './components/Inline.svelte';
46
+ export { default as Text } from './components/Text.svelte';
47
+ export { default as Disclosure } from './components/Disclosure.svelte';
48
+ export { default as NavSection } from './components/NavSection.svelte';
49
+ export { default as Spacer } from './components/Spacer.svelte';
50
+ export { default as Centered } from './components/Centered.svelte';
51
+ export { default as Prose } from './components/Prose.svelte';
52
+ export { default as CanvasStage } from './components/CanvasStage.svelte';
53
+ export { default as CalendarGrid } from './components/CalendarGrid.svelte';
54
+ export { default as DocumentViewer } from './components/DocumentViewer.svelte';
55
+ export type { ViewerMark } from './utils/componentTypes.js';
56
+ export { default as DataTable } from './components/DataTable.svelte';
57
+ export type { DataColumn } from './utils/componentTypes.js';
58
+ export { default as List } from './components/List.svelte';
59
+ export { default as ListItem } from './components/ListItem.svelte';
60
+ export { default as DescriptionList } from './components/DescriptionList.svelte';
61
+ export type { DescriptionItem } from './utils/componentTypes.js';
62
+ export { default as FormRow } from './components/FormRow.svelte';
63
+ export { default as SearchPicker } from './components/SearchPicker.svelte';
64
+ export { default as FileButton } from './components/FileButton.svelte';
65
+ export { default as TitleInput } from './components/TitleInput.svelte';
66
+ export type { PickerOption } from './utils/componentTypes.js';
67
+ export { default as RadioCards } from './components/RadioCards.svelte';
68
+ export type { RadioCardOption } from './utils/componentTypes.js';
69
+ export { default as SegmentedControl } from './components/SegmentedControl.svelte';
70
+ export type { SegmentOption } from './utils/componentTypes.js';
71
+ export { default as ContextMenu } from './components/ContextMenu.svelte';
72
+ export { default as Drawer } from './components/Drawer.svelte';
73
+ export { addDays, calendarRange, eventsOn, sameDay, shiftCalendar, startOfDay, startOfWeek, type CalendarEvent, type CalendarMode, } from './utils/calendar.js';
package/dist/index.js CHANGED
@@ -36,3 +36,34 @@ export { default as Tabs } from './components/Tabs.svelte';
36
36
  export { default as Textarea } from './components/Textarea.svelte';
37
37
  export { default as Toaster } from './components/Toaster.svelte';
38
38
  export { default as Tooltip } from './components/Tooltip.svelte';
39
+ // Layout
40
+ export { default as Page } from './components/Page.svelte';
41
+ export { default as PageHeader } from './components/PageHeader.svelte';
42
+ export { default as Section } from './components/Section.svelte';
43
+ export { default as Stack } from './components/Stack.svelte';
44
+ export { default as Inline } from './components/Inline.svelte';
45
+ export { default as Text } from './components/Text.svelte';
46
+ export { default as Disclosure } from './components/Disclosure.svelte';
47
+ export { default as NavSection } from './components/NavSection.svelte';
48
+ export { default as Spacer } from './components/Spacer.svelte';
49
+ export { default as Centered } from './components/Centered.svelte';
50
+ export { default as Prose } from './components/Prose.svelte';
51
+ export { default as CanvasStage } from './components/CanvasStage.svelte';
52
+ export { default as CalendarGrid } from './components/CalendarGrid.svelte';
53
+ export { default as DocumentViewer } from './components/DocumentViewer.svelte';
54
+ // Data display
55
+ export { default as DataTable } from './components/DataTable.svelte';
56
+ export { default as List } from './components/List.svelte';
57
+ export { default as ListItem } from './components/ListItem.svelte';
58
+ export { default as DescriptionList } from './components/DescriptionList.svelte';
59
+ export { default as FormRow } from './components/FormRow.svelte';
60
+ // Inputs
61
+ export { default as SearchPicker } from './components/SearchPicker.svelte';
62
+ export { default as FileButton } from './components/FileButton.svelte';
63
+ export { default as TitleInput } from './components/TitleInput.svelte';
64
+ export { default as RadioCards } from './components/RadioCards.svelte';
65
+ export { default as SegmentedControl } from './components/SegmentedControl.svelte';
66
+ // Overlays
67
+ export { default as ContextMenu } from './components/ContextMenu.svelte';
68
+ export { default as Drawer } from './components/Drawer.svelte';
69
+ export { addDays, calendarRange, eventsOn, sameDay, shiftCalendar, startOfDay, startOfWeek, } from './utils/calendar.js';
@@ -0,0 +1,48 @@
1
+ /** Wall-clock calendar helpers (local time zone) for week and month views. */
2
+ export type CalendarMode = 'week' | 'month';
3
+ export type CalendarEvent = {
4
+ id: string;
5
+ title: string;
6
+ start: Date;
7
+ end: Date;
8
+ allDay: boolean;
9
+ /** Dimmed (e.g. "free" / transparent events). */
10
+ muted?: boolean;
11
+ /** Accent colour (palette name or CSS colour). */
12
+ color?: string;
13
+ };
14
+ export declare const MINUTES_PER_DAY: number;
15
+ export declare function startOfDay(d: Date): Date;
16
+ /** Monday of the week containing `d`. */
17
+ export declare function startOfWeek(d: Date): Date;
18
+ export declare function addDays(d: Date, n: number): Date;
19
+ export declare function sameDay(a: Date, b: Date): boolean;
20
+ /** Visible range `[start, end)` around `anchor`: a Monday-start week or a calendar month. */
21
+ export declare function calendarRange(anchor: Date, mode: CalendarMode): {
22
+ start: Date;
23
+ end: Date;
24
+ };
25
+ /** Move the anchor by `delta` weeks or months. */
26
+ export declare function shiftCalendar(anchor: Date, mode: CalendarMode, delta: number): Date;
27
+ /** Six Monday-start weeks covering the month of `monthStart`. */
28
+ export declare function monthGrid(monthStart: Date): Date[];
29
+ /** Events showing on `day` (multi-day all-day events on each day), all-day first, then by start time. */
30
+ export declare function eventsOn(events: CalendarEvent[], day: Date): CalendarEvent[];
31
+ /** Vertical position of a timed event in a day column, as percentages of the day. */
32
+ export declare function dayLayout(event: CalendarEvent): {
33
+ top: number;
34
+ height: number;
35
+ };
36
+ export type PlacedEvent = {
37
+ event: CalendarEvent;
38
+ /** Percent of the day from the top. */
39
+ top: number;
40
+ height: number;
41
+ /** Side-by-side column within its overlap group, and how many columns the group has. */
42
+ lane: number;
43
+ lanes: number;
44
+ /** Short enough to render as one line. */
45
+ compact: boolean;
46
+ };
47
+ /** Lay out a day's timed events so overlapping ones sit side by side instead of on top of each other. */
48
+ export declare function layoutDay(events: CalendarEvent[]): PlacedEvent[];