@sveltier/ui 0.1.0-alpha.0 → 0.1.0-alpha.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 (71) hide show
  1. package/dist/components/Accordion/Accordion.svelte +74 -0
  2. package/dist/components/Accordion/Accordion.svelte.d.ts +25 -0
  3. package/dist/components/Accordion/accordion.css +88 -0
  4. package/dist/components/Accordion/index.d.ts +2 -0
  5. package/dist/components/Accordion/index.js +1 -0
  6. package/dist/components/Accordion/types.d.ts +64 -0
  7. package/dist/components/Accordion/types.js +1 -0
  8. package/dist/components/Dialog/Dialog.svelte +36 -0
  9. package/dist/components/Dialog/Dialog.svelte.d.ts +4 -0
  10. package/dist/components/Dialog/index.d.ts +2 -0
  11. package/dist/components/Dialog/index.js +1 -0
  12. package/dist/components/Dialog/types.d.ts +50 -0
  13. package/dist/components/Dialog/types.js +1 -0
  14. package/dist/components/Menu/Menu.svelte +195 -0
  15. package/dist/components/Menu/Menu.svelte.d.ts +4 -0
  16. package/dist/components/Menu/index.d.ts +2 -0
  17. package/dist/components/Menu/index.js +1 -0
  18. package/dist/components/Menu/menu.css +103 -0
  19. package/dist/components/Menu/types.d.ts +90 -0
  20. package/dist/components/Menu/types.js +1 -0
  21. package/dist/components/Modal/Modal.svelte +146 -0
  22. package/dist/components/Modal/Modal.svelte.d.ts +4 -0
  23. package/dist/components/Modal/modal.css +150 -0
  24. package/dist/components/Modal/types.d.ts +54 -0
  25. package/dist/components/Modal/types.js +1 -0
  26. package/dist/components/Popover/Popover.svelte +115 -0
  27. package/dist/components/Popover/Popover.svelte.d.ts +4 -0
  28. package/dist/components/Popover/index.d.ts +2 -0
  29. package/dist/components/Popover/index.js +1 -0
  30. package/dist/components/Popover/popover.css +67 -0
  31. package/dist/components/Popover/types.d.ts +83 -0
  32. package/dist/components/Popover/types.js +1 -0
  33. package/dist/components/Sheet/Sheet.svelte +56 -0
  34. package/dist/components/Sheet/Sheet.svelte.d.ts +4 -0
  35. package/dist/components/Sheet/index.d.ts +2 -0
  36. package/dist/components/Sheet/index.js +2 -0
  37. package/dist/components/Sheet/sheet.css +61 -0
  38. package/dist/components/Sheet/types.d.ts +51 -0
  39. package/dist/components/Sheet/types.js +1 -0
  40. package/dist/components/Tooltip/Tooltip.svelte +161 -0
  41. package/dist/components/Tooltip/Tooltip.svelte.d.ts +4 -0
  42. package/dist/components/Tooltip/index.d.ts +2 -0
  43. package/dist/components/Tooltip/index.js +1 -0
  44. package/dist/components/Tooltip/tooltip.css +44 -0
  45. package/dist/components/Tooltip/types.d.ts +55 -0
  46. package/dist/components/Tooltip/types.js +1 -0
  47. package/dist/core/errors/codes.d.ts +15 -3
  48. package/dist/core/errors/codes.js +15 -3
  49. package/dist/core/locale/locale.d.ts +1 -0
  50. package/dist/core/locale/locale.js +2 -0
  51. package/dist/core/overlay/types.d.ts +33 -0
  52. package/dist/core/overlay/types.js +1 -0
  53. package/dist/core/provider/UIProvider.svelte +5 -2
  54. package/dist/core/theme/css.js +6 -2
  55. package/dist/core/toast/ToastOutlet.svelte +192 -0
  56. package/dist/core/toast/ToastOutlet.svelte.d.ts +11 -0
  57. package/dist/core/toast/ToastProvider.svelte +39 -0
  58. package/dist/core/toast/ToastProvider.svelte.d.ts +19 -0
  59. package/dist/core/toast/toast.css +134 -0
  60. package/dist/core/toast/toast.svelte.d.ts +117 -0
  61. package/dist/core/toast/toast.svelte.js +133 -0
  62. package/dist/dev/off.d.ts +1 -0
  63. package/dist/dev/off.js +1 -0
  64. package/dist/dev/on.d.ts +14 -2
  65. package/dist/dev/on.js +22 -6
  66. package/dist/index.d.ts +9 -0
  67. package/dist/index.js +11 -0
  68. package/dist/primitives/layer/dismissable.d.ts +6 -0
  69. package/dist/primitives/layer/dismissable.js +11 -4
  70. package/dist/styles/props.css +5 -2
  71. package/package.json +1 -1
package/dist/dev/off.d.ts CHANGED
@@ -2,3 +2,4 @@ import type * as On from './on.js';
2
2
  export declare const DEV: boolean;
3
3
  export declare const checkValue: typeof On.checkValue;
4
4
  export declare const warnUnnamed: typeof On.warnUnnamed;
5
+ export declare const warnNamelessTrigger: typeof On.warnNamelessTrigger;
package/dist/dev/off.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export const DEV = false;
2
2
  export const checkValue = () => { };
3
3
  export const warnUnnamed = () => { };
4
+ export const warnNamelessTrigger = () => { };
package/dist/dev/on.d.ts CHANGED
@@ -4,5 +4,17 @@ export declare const DEV: boolean;
4
4
  * likely intent, for example the prop the value belongs to.
5
5
  */
6
6
  export declare function checkValue(component: string, prop: string, value: unknown, valid: readonly unknown[], hint?: string): void;
7
- /** Warns when a form control has no accessible name: no label with text, and no ARIA name. */
8
- export declare function warnUnnamed(component: string, control: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null | undefined): void;
7
+ /**
8
+ * Warns when a form control or a dialog has no accessible name: no label with text, and no ARIA
9
+ * name. `give` names what to add, as the message says it ("a label", "a title").
10
+ */
11
+ export declare function warnUnnamed(component: string, element: (HTMLElement & {
12
+ labels?: NodeListOf<HTMLLabelElement> | null;
13
+ }) | null | undefined, give?: string): void;
14
+ /**
15
+ * Warns when a tooltip describes a control that has no accessible name: a description names
16
+ * nothing, so an icon-only button would be announced as just "button".
17
+ */
18
+ export declare function warnNamelessTrigger(component: string, element: HTMLElement & {
19
+ labels?: NodeListOf<HTMLLabelElement> | null;
20
+ }): void;
package/dist/dev/on.js CHANGED
@@ -20,14 +20,30 @@ export function checkValue(component, prop, value, valid, hint) {
20
20
  const got = typeof value === 'string' ? `"${value}"` : `{${String(value)}}`;
21
21
  warn('SV2002', `<${component}> got ${prop}=${got}. Valid values: ${valid.map(show).join(' | ')}.${hint ? ` ${hint}` : ''}`);
22
22
  }
23
- /** Warns when a form control has no accessible name: no label with text, and no ARIA name. */
24
- export function warnUnnamed(component, control) {
25
- if (!control)
23
+ /**
24
+ * Warns when a form control or a dialog has no accessible name: no label with text, and no ARIA
25
+ * name. `give` names what to add, as the message says it ("a label", "a title").
26
+ */
27
+ export function warnUnnamed(component, element, give = 'a label') {
28
+ if (!element)
26
29
  return;
27
30
  // A label that wraps the control but holds no text names nothing.
28
- if ([...(control.labels ?? [])].some((label) => label.textContent?.trim()))
31
+ if ([...(element.labels ?? [])].some((label) => label.textContent?.trim()))
32
+ return;
33
+ if (element.getAttribute('aria-label') || element.getAttribute('aria-labelledby'))
29
34
  return;
30
- if (control.getAttribute('aria-label') || control.getAttribute('aria-labelledby'))
35
+ warn('SV5001', `<${component}> has no accessible name. Give it ${give}, or name it with aria-label or aria-labelledby.`);
36
+ }
37
+ /**
38
+ * Warns when a tooltip describes a control that has no accessible name: a description names
39
+ * nothing, so an icon-only button would be announced as just "button".
40
+ */
41
+ export function warnNamelessTrigger(component, element) {
42
+ if (element.textContent?.trim() ||
43
+ element.querySelector('img[alt]:not([alt=""])') ||
44
+ ['aria-label', 'aria-labelledby', 'title'].some((name) => element.getAttribute(name)) ||
45
+ [...(element.labels ?? [])].some((label) => label.textContent?.trim())) {
31
46
  return;
32
- warn('SV5001', `<${component}> has no accessible name. Give it a label, or name it with aria-label or aria-labelledby.`);
47
+ }
48
+ warn('SV4002', `<${component}> describes a control that has no accessible name. A tooltip adds a description, not a name: give the control aria-label, as every icon-only button needs, or visible text.`);
33
49
  }
package/dist/index.d.ts CHANGED
@@ -19,6 +19,9 @@ export { BREAKPOINTS, useDisplay, type Breakpoint, type DisplayInstance, type Di
19
19
  export { MESSAGES, useLocale, type LocaleInstance, type LocaleOptions, type MessageKey, type Messages } from './core/locale/locale.js';
20
20
  export { ERROR_CODES, type ErrorCode, type ErrorEntry } from './core/errors/codes.js';
21
21
  export type { FieldError, Rule, ValidateOn } from './core/form/types.js';
22
+ export { CLOSE_REASONS, type CloseReason, type TriggerAttributes } from './core/overlay/types.js';
23
+ export { default as ToastProvider, type ToastProviderProps } from './core/toast/ToastProvider.svelte';
24
+ export { useToast, type ToastAction, type ToastDefaults, type ToastInstance, type ToastOptions } from './core/toast/toast.svelte.js';
22
25
  export { focusTrap, type FocusTrapOptions } from './primitives/focus/focus-trap.js';
23
26
  export { rovingFocus, type RovingFocusOptions } from './primitives/focus/roving-focus.js';
24
27
  export { isTabbable, tabbable, type FocusableElement } from './primitives/focus/tabbable.js';
@@ -32,6 +35,7 @@ export { typeahead, type TypeaheadOptions } from './primitives/keyboard/typeahea
32
35
  export { cubicBezier } from './primitives/motion/easing.js';
33
36
  export { easing, fade, motion, pop, rise, spring, SPRINGS, type Motion, type SpringPreset, type TransitionOptions } from './primitives/motion/motion.js';
34
37
  export { virtualList, type ScrollToIndexOptions, type VirtualItem, type VirtualKey, type VirtualList, type VirtualListOptions } from './primitives/virtual/virtual-list.svelte.js';
38
+ export { Accordion, type AccordionDefaults, type AccordionItem, type AccordionProps } from './components/Accordion/index.js';
35
39
  export { Alert, type AlertDefaults, type AlertProps } from './components/Alert/index.js';
36
40
  export { Avatar, type AvatarDefaults, type AvatarProps } from './components/Avatar/index.js';
37
41
  export { Badge, type BadgeDefaults, type BadgeProps } from './components/Badge/index.js';
@@ -40,19 +44,24 @@ export { ButtonGroup, type ButtonGroupDefaults, type ButtonGroupProps } from './
40
44
  export { Card, type CardDefaults, type CardProps } from './components/Card/index.js';
41
45
  export { Checkbox, type CheckboxDefaults, type CheckboxProps } from './components/Checkbox/index.js';
42
46
  export { Chip, type ChipDefaults, type ChipProps } from './components/Chip/index.js';
47
+ export { Dialog, type DialogDefaults, type DialogProps } from './components/Dialog/index.js';
43
48
  export { Divider, type DividerProps } from './components/Divider/index.js';
44
49
  export { Field, FIELD_VARIANTS, type FieldContentProps, type FieldControlAttributes, type FieldDefaults, type FieldProps, type FieldVariant } from './components/Field/index.js';
45
50
  export { Form, type FormProps } from './components/Form/index.js';
46
51
  export { Icon, type IconProps } from './components/Icon/index.js';
47
52
  export { List, ListItem, type ListDefaults, type ListItemProps, type ListProps } from './components/List/index.js';
53
+ export { Menu, type MenuAction, type MenuDefaults, type MenuHeading, type MenuItem, type MenuProps, type MenuSeparator } from './components/Menu/index.js';
48
54
  export { NativeSelect, type NativeSelectDefaults, type NativeSelectOption, type NativeSelectProps } from './components/NativeSelect/index.js';
49
55
  export { NumberField, type NumberFieldDefaults, type NumberFieldProps } from './components/NumberField/index.js';
56
+ export { Popover, type PopoverDefaults, type PopoverProps } from './components/Popover/index.js';
50
57
  export { ProgressCircular, ProgressLinear, type ProgressCircularDefaults, type ProgressCircularProps, type ProgressLinearDefaults, type ProgressLinearProps } from './components/Progress/index.js';
51
58
  export { RadioGroup, type RadioGroupDefaults, type RadioGroupOption, type RadioGroupProps } from './components/RadioGroup/index.js';
52
59
  export { SegmentedControl, type SegmentedControlDefaults, type SegmentedControlOption, type SegmentedControlProps } from './components/SegmentedControl/index.js';
60
+ export { Sheet, SHEET_SIDES, type SheetDefaults, type SheetProps, type SheetSide } from './components/Sheet/index.js';
53
61
  export { Skeleton, type SkeletonProps } from './components/Skeleton/index.js';
54
62
  export { Slider, type SliderDefaults, type SliderProps, type SliderTick } from './components/Slider/index.js';
55
63
  export { Switch, type SwitchDefaults, type SwitchProps } from './components/Switch/index.js';
56
64
  export { Tabs, type TabsDefaults, type TabsItem, type TabsProps } from './components/Tabs/index.js';
57
65
  export { Textarea, type TextareaDefaults, type TextareaProps } from './components/Textarea/index.js';
58
66
  export { TextField, type TextFieldDefaults, type TextFieldProps, type TextFieldType } from './components/TextField/index.js';
67
+ export { Tooltip, type TooltipDefaults, type TooltipProps } from './components/Tooltip/index.js';
package/dist/index.js CHANGED
@@ -25,6 +25,11 @@ export { BREAKPOINTS, useDisplay } from './core/display/display.js';
25
25
  export { MESSAGES, useLocale } from './core/locale/locale.js';
26
26
  // Errors
27
27
  export { ERROR_CODES } from './core/errors/codes.js';
28
+ // Overlays: what an overlay hands to the control that opens it
29
+ export { CLOSE_REASONS } from './core/overlay/types.js';
30
+ // Toasts
31
+ export { default as ToastProvider } from './core/toast/ToastProvider.svelte';
32
+ export { useToast } from './core/toast/toast.svelte.js';
28
33
  // Primitives: focus
29
34
  export { focusTrap } from './primitives/focus/focus-trap.js';
30
35
  export { rovingFocus } from './primitives/focus/roving-focus.js';
@@ -46,6 +51,7 @@ export { easing, fade, motion, pop, rise, spring, SPRINGS } from './primitives/m
46
51
  // Primitives: virtual lists
47
52
  export { virtualList } from './primitives/virtual/virtual-list.svelte.js';
48
53
  // Components
54
+ export { Accordion } from './components/Accordion/index.js';
49
55
  export { Alert } from './components/Alert/index.js';
50
56
  export { Avatar } from './components/Avatar/index.js';
51
57
  export { Badge } from './components/Badge/index.js';
@@ -54,19 +60,24 @@ export { ButtonGroup } from './components/ButtonGroup/index.js';
54
60
  export { Card } from './components/Card/index.js';
55
61
  export { Checkbox } from './components/Checkbox/index.js';
56
62
  export { Chip } from './components/Chip/index.js';
63
+ export { Dialog } from './components/Dialog/index.js';
57
64
  export { Divider } from './components/Divider/index.js';
58
65
  export { Field, FIELD_VARIANTS } from './components/Field/index.js';
59
66
  export { Form } from './components/Form/index.js';
60
67
  export { Icon } from './components/Icon/index.js';
61
68
  export { List, ListItem } from './components/List/index.js';
69
+ export { Menu } from './components/Menu/index.js';
62
70
  export { NativeSelect } from './components/NativeSelect/index.js';
63
71
  export { NumberField } from './components/NumberField/index.js';
72
+ export { Popover } from './components/Popover/index.js';
64
73
  export { ProgressCircular, ProgressLinear } from './components/Progress/index.js';
65
74
  export { RadioGroup } from './components/RadioGroup/index.js';
66
75
  export { SegmentedControl } from './components/SegmentedControl/index.js';
76
+ export { Sheet, SHEET_SIDES } from './components/Sheet/index.js';
67
77
  export { Skeleton } from './components/Skeleton/index.js';
68
78
  export { Slider } from './components/Slider/index.js';
69
79
  export { Switch } from './components/Switch/index.js';
70
80
  export { Tabs } from './components/Tabs/index.js';
71
81
  export { Textarea } from './components/Textarea/index.js';
72
82
  export { TextField } from './components/TextField/index.js';
83
+ export { Tooltip } from './components/Tooltip/index.js';
@@ -13,6 +13,12 @@ export interface DismissableOptions {
13
13
  focusOutside?: boolean;
14
14
  /** Elements that count as inside, such as the trigger, which toggles instead. */
15
15
  inside?: Elements | (() => Elements);
16
+ /**
17
+ * A layer the user does not work in, such as a tooltip. Escape closes it first, as the
18
+ * topmost layer, but a press outside closes it and still reaches the layer beneath, and focus
19
+ * moving out is left to the layers beneath. Defaults to `false`.
20
+ */
21
+ transient?: boolean;
16
22
  }
17
23
  /**
18
24
  * Registers the element as a layer: Escape, a press outside, or (opt-in) focus leaving it
@@ -14,10 +14,17 @@ function isInside({ element, options }, target) {
14
14
  const onScrollbar = (event) => event.target === document.documentElement &&
15
15
  (event.clientX >= document.documentElement.clientWidth ||
16
16
  event.clientY >= document.documentElement.clientHeight);
17
+ // The press goes to the topmost layer, through any transient layers above it, which close.
17
18
  function dismissOutside(event) {
18
- const top = layers.at(-1);
19
- if (top && top.options.outside !== false && !isInside(top, event.target) && !onScrollbar(event)) {
20
- top.options.onDismiss('outside');
19
+ if (onScrollbar(event))
20
+ return;
21
+ for (const layer of layers.toReversed()) {
22
+ if (isInside(layer, event.target))
23
+ return;
24
+ if (layer.options.outside !== false)
25
+ layer.options.onDismiss('outside');
26
+ if (!layer.options.transient)
27
+ return;
21
28
  }
22
29
  }
23
30
  // Escape listens in the bubble phase, so handlers inside run first and can prevent it.
@@ -40,7 +47,7 @@ function onclick(event) {
40
47
  touch = false;
41
48
  }
42
49
  function onfocusin(event) {
43
- const top = layers.at(-1);
50
+ const top = layers.findLast((layer) => !layer.options.transient);
44
51
  if (top?.options.focusOutside && !isInside(top, event.target))
45
52
  top.options.onDismiss('focus');
46
53
  }
@@ -57,8 +57,11 @@
57
57
  --sv-variant-shadow: none;
58
58
  }
59
59
 
60
- /* Plain: no decoration in any state. */
61
- .sv-variant-plain {
60
+ /*
61
+ * Plain: no decoration in any state, on a control itself. The washes inherit, so a plain
62
+ * container (a Card, an Alert, a List) leaves them alone for the controls inside it.
63
+ */
64
+ .sv-variant-plain:where(a, button, summary, [role='button'], [role='link']) {
62
65
  --sv-state-hover: 0%;
63
66
  --sv-state-press: 0%;
64
67
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltier/ui",
3
- "version": "0.1.0-alpha.0",
3
+ "version": "0.1.0-alpha.1",
4
4
  "description": "The UI framework for AI coding agents, on Svelte 5: one typed vocabulary, docs generated from the types, and errors that say how to fix them.",
5
5
  "license": "MIT",
6
6
  "repository": {