@human-synthesis/norns-ui 0.0.2 → 0.0.5

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 (145) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -129
  3. package/package.json +23 -15
  4. package/src/auto-import.js +96 -22
  5. package/src/components/Accordion.n +38 -0
  6. package/src/components/Audio.n +24 -0
  7. package/src/components/Autocomplete.n +59 -0
  8. package/src/components/Avatar.n +27 -0
  9. package/src/components/AvatarGroup.n +25 -0
  10. package/src/components/Badge.n +20 -0
  11. package/src/components/Banner.n +25 -0
  12. package/src/components/Breadcrumbs.n +22 -0
  13. package/src/components/Btn.n +29 -8
  14. package/src/components/ButtonGroup.n +14 -0
  15. package/src/components/Calendar.n +153 -0
  16. package/src/components/Card.n +34 -0
  17. package/src/components/Carousel.n +66 -0
  18. package/src/components/Chip.n +27 -0
  19. package/src/components/Collapsible.n +32 -0
  20. package/src/components/ColorPicker.n +62 -0
  21. package/src/components/ContextMenu.n +48 -0
  22. package/src/components/CopyButton.n +50 -0
  23. package/src/components/DataTable.n +61 -0
  24. package/src/components/DatePicker.n +68 -0
  25. package/src/components/DateRangePicker.n +59 -0
  26. package/src/components/Dialog.n +54 -0
  27. package/src/components/Drawer.n +49 -0
  28. package/src/components/Dropdown.n +41 -0
  29. package/src/components/Field.n +29 -20
  30. package/src/components/Form.n +22 -0
  31. package/src/components/GradientText.n +21 -0
  32. package/src/components/Header.n +23 -0
  33. package/src/components/HeroBanner.n +37 -0
  34. package/src/components/HierarchicalMenu.n +38 -0
  35. package/src/components/Icon.n +16 -0
  36. package/src/components/Image.n +31 -0
  37. package/src/components/MegaMenu.n +36 -0
  38. package/src/components/MultiSelect.n +56 -0
  39. package/src/components/NumberInput.n +49 -0
  40. package/src/components/OtpField.n +67 -0
  41. package/src/components/Pagination.n +73 -0
  42. package/src/components/Popover.n +32 -0
  43. package/src/components/PreviewCard.n +30 -0
  44. package/src/components/Progress.n +26 -0
  45. package/src/components/ProgressCircular.n +52 -0
  46. package/src/components/RichTooltip.n +33 -0
  47. package/src/components/RippleButton.n +56 -0
  48. package/src/components/ScrollArea.n +31 -0
  49. package/src/components/Separator.n +12 -0
  50. package/src/components/Sheet.n +55 -0
  51. package/src/components/ShinyButton.n +36 -0
  52. package/src/components/Skeleton.n +27 -0
  53. package/src/components/Stepper.n +35 -0
  54. package/src/components/Surface.n +10 -0
  55. package/src/components/Tabs.n +28 -0
  56. package/src/components/TagsInput.n +66 -0
  57. package/src/components/ThemeToggler.n +43 -0
  58. package/src/components/TimePicker.n +166 -0
  59. package/src/components/Timeline.n +27 -0
  60. package/src/components/ToastProvider.n +16 -0
  61. package/src/components/ToggleButton.n +29 -0
  62. package/src/components/ToggleButtonGroup.n +34 -0
  63. package/src/components/Toolbar.n +15 -0
  64. package/src/components/Tooltip.n +34 -0
  65. package/src/components/Tree.n +57 -0
  66. package/src/components/Uploader.n +88 -0
  67. package/src/components/Video.n +26 -0
  68. package/src/index.js +76 -0
  69. package/src/lib/toast.svelte.js +42 -0
  70. package/src/motion/AnimatedNumber.n +55 -0
  71. package/src/motion/GradientBackground.n +25 -0
  72. package/src/motion/LiquidButton.n +48 -0
  73. package/src/motion/Reveal.n +37 -0
  74. package/src/motion/Sparkles.n +53 -0
  75. package/src/motion/index.js +18 -0
  76. package/src/styles/atoms.css +1794 -71
  77. package/src/styles/tokens.css +171 -40
  78. package/src/types/Accordion.d.ts +17 -0
  79. package/src/types/AnimatedNumber.d.ts +15 -0
  80. package/src/types/Audio.d.ts +18 -0
  81. package/src/types/Autocomplete.d.ts +17 -0
  82. package/src/types/Avatar.d.ts +14 -0
  83. package/src/types/AvatarGroup.d.ts +15 -0
  84. package/src/types/Badge.d.ts +14 -0
  85. package/src/types/Banner.d.ts +15 -0
  86. package/src/types/Breadcrumbs.d.ts +15 -0
  87. package/src/types/Btn.d.ts +10 -0
  88. package/src/types/ButtonGroup.d.ts +10 -0
  89. package/src/types/Calendar.d.ts +20 -0
  90. package/src/types/Card.d.ts +19 -0
  91. package/src/types/Carousel.d.ts +23 -0
  92. package/src/types/Chip.d.ts +12 -0
  93. package/src/types/Collapsible.d.ts +12 -0
  94. package/src/types/ColorPicker.d.ts +15 -0
  95. package/src/types/ContextMenu.d.ts +19 -0
  96. package/src/types/CopyButton.d.ts +16 -0
  97. package/src/types/DataTable.d.ts +27 -0
  98. package/src/types/DatePicker.d.ts +18 -0
  99. package/src/types/DateRangePicker.d.ts +17 -0
  100. package/src/types/Dialog.d.ts +17 -0
  101. package/src/types/Drawer.d.ts +18 -0
  102. package/src/types/Dropdown.d.ts +23 -0
  103. package/src/types/Field.d.ts +14 -3
  104. package/src/types/Form.d.ts +17 -0
  105. package/src/types/GradientBackground.d.ts +14 -0
  106. package/src/types/GradientText.d.ts +19 -0
  107. package/src/types/Header.d.ts +12 -0
  108. package/src/types/HeroBanner.d.ts +17 -0
  109. package/src/types/HierarchicalMenu.d.ts +20 -0
  110. package/src/types/Icon.d.ts +21 -0
  111. package/src/types/Image.d.ts +15 -0
  112. package/src/types/LiquidButton.d.ts +15 -0
  113. package/src/types/MegaMenu.d.ts +29 -0
  114. package/src/types/MultiSelect.d.ts +13 -0
  115. package/src/types/NumberInput.d.ts +17 -0
  116. package/src/types/OtpField.d.ts +13 -0
  117. package/src/types/Pagination.d.ts +13 -0
  118. package/src/types/Popover.d.ts +18 -0
  119. package/src/types/PreviewCard.d.ts +16 -0
  120. package/src/types/Progress.d.ts +14 -0
  121. package/src/types/ProgressCircular.d.ts +14 -0
  122. package/src/types/Reveal.d.ts +20 -0
  123. package/src/types/RichTooltip.d.ts +16 -0
  124. package/src/types/RippleButton.d.ts +15 -0
  125. package/src/types/ScrollArea.d.ts +11 -0
  126. package/src/types/Separator.d.ts +9 -0
  127. package/src/types/Sheet.d.ts +20 -0
  128. package/src/types/ShinyButton.d.ts +15 -0
  129. package/src/types/Skeleton.d.ts +13 -0
  130. package/src/types/Sparkles.d.ts +13 -0
  131. package/src/types/Stepper.d.ts +19 -0
  132. package/src/types/Surface.d.ts +10 -0
  133. package/src/types/Tabs.d.ts +17 -0
  134. package/src/types/TagsInput.d.ts +17 -0
  135. package/src/types/ThemeToggler.d.ts +17 -0
  136. package/src/types/TimePicker.d.ts +20 -0
  137. package/src/types/Timeline.d.ts +17 -0
  138. package/src/types/ToastProvider.d.ts +15 -0
  139. package/src/types/ToggleButton.d.ts +15 -0
  140. package/src/types/ToggleButtonGroup.d.ts +20 -0
  141. package/src/types/Toolbar.d.ts +12 -0
  142. package/src/types/Tooltip.d.ts +15 -0
  143. package/src/types/Tree.d.ts +20 -0
  144. package/src/types/Uploader.d.ts +15 -0
  145. package/src/types/Video.d.ts +20 -0
package/src/index.js CHANGED
@@ -21,7 +21,83 @@ export { default as Select } from './components/Select.n';
21
21
  export { default as Switch } from './components/Switch.n';
22
22
  export { default as Textarea } from './components/Textarea.n';
23
23
 
24
+ // Phase 3 — behavior tier (Bits UI)
25
+ export { default as Dialog } from './components/Dialog.n';
26
+ export { default as Sheet } from './components/Sheet.n';
27
+ export { default as Popover } from './components/Popover.n';
28
+ export { default as Dropdown } from './components/Dropdown.n';
29
+ export { default as Tooltip } from './components/Tooltip.n';
30
+ export { default as Tabs } from './components/Tabs.n';
31
+ export { default as ToastProvider } from './components/ToastProvider.n';
32
+
33
+ // 0.0.4 — display layer
34
+ export { default as Icon } from './components/Icon.n';
35
+ export { default as Card } from './components/Card.n';
36
+ export { default as Surface } from './components/Surface.n';
37
+ export { default as Banner } from './components/Banner.n';
38
+ export { default as Badge } from './components/Badge.n';
39
+ export { default as Chip } from './components/Chip.n';
40
+ export { default as Avatar } from './components/Avatar.n';
41
+ export { default as Skeleton } from './components/Skeleton.n';
42
+ export { default as Progress } from './components/Progress.n';
43
+ export { default as ProgressCircular } from './components/ProgressCircular.n';
44
+
45
+ // 0.0.4 — composite layer
46
+ export { default as Header } from './components/Header.n';
47
+ export { default as Drawer } from './components/Drawer.n';
48
+ export { default as HeroBanner } from './components/HeroBanner.n';
49
+ export { default as Stepper } from './components/Stepper.n';
50
+ export { default as Breadcrumbs } from './components/Breadcrumbs.n';
51
+ export { default as Pagination } from './components/Pagination.n';
52
+ export { default as Accordion } from './components/Accordion.n';
53
+ export { default as Carousel } from './components/Carousel.n';
54
+ export { default as Tree } from './components/Tree.n';
55
+
56
+ // 0.0.4 — wave A
57
+ export { default as Separator } from './components/Separator.n';
58
+ export { default as Toolbar } from './components/Toolbar.n';
59
+ export { default as ButtonGroup } from './components/ButtonGroup.n';
60
+ export { default as ToggleButton } from './components/ToggleButton.n';
61
+ export { default as ToggleButtonGroup } from './components/ToggleButtonGroup.n';
62
+ export { default as Collapsible } from './components/Collapsible.n';
63
+ export { default as NumberInput } from './components/NumberInput.n';
64
+ export { default as OtpField } from './components/OtpField.n';
65
+ export { default as TagsInput } from './components/TagsInput.n';
66
+ export { default as Image } from './components/Image.n';
67
+ export { default as Audio } from './components/Audio.n';
68
+ export { default as Video } from './components/Video.n';
69
+ export { default as Timeline } from './components/Timeline.n';
70
+
71
+ // 0.0.4 — wave B
72
+ export { default as Autocomplete } from './components/Autocomplete.n';
73
+ export { default as MultiSelect } from './components/MultiSelect.n';
74
+ export { default as ContextMenu } from './components/ContextMenu.n';
75
+ export { default as RichTooltip } from './components/RichTooltip.n';
76
+ export { default as PreviewCard } from './components/PreviewCard.n';
77
+ export { default as ScrollArea } from './components/ScrollArea.n';
78
+ export { default as ColorPicker } from './components/ColorPicker.n';
79
+ export { default as Uploader } from './components/Uploader.n';
80
+ export { default as HierarchicalMenu } from './components/HierarchicalMenu.n';
81
+ export { default as MegaMenu } from './components/MegaMenu.n';
82
+
83
+ // 0.0.4 — wave C
84
+ export { default as DatePicker } from './components/DatePicker.n';
85
+ export { default as DateRangePicker } from './components/DateRangePicker.n';
86
+ export { default as TimePicker } from './components/TimePicker.n';
87
+ export { default as Calendar } from './components/Calendar.n';
88
+ export { default as DataTable } from './components/DataTable.n';
89
+
90
+ // 0.0.5 — CSS-only motion components
91
+ export { default as AvatarGroup } from './components/AvatarGroup.n';
92
+ export { default as GradientText } from './components/GradientText.n';
93
+ export { default as CopyButton } from './components/CopyButton.n';
94
+ export { default as ThemeToggler } from './components/ThemeToggler.n';
95
+ export { default as ShinyButton } from './components/ShinyButton.n';
96
+ export { default as RippleButton } from './components/RippleButton.n';
97
+ // Motion-driven: `import … from '@human-synthesis/norns-ui/motion'`.
98
+
24
99
  // Helpers
25
100
  export { cn } from './lib/cn.js';
26
101
  export { variantClasses } from './lib/variants.js';
27
102
  export { presetUI } from './auto-import.js';
103
+ export { toast, notify, dismiss, clear } from './lib/toast.svelte.js';
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Toast store + helpers. Single in-process queue, mounted once via
3
+ * <ToastProvider>. `toast(msg)` pushes from anywhere — server actions,
4
+ * client effects, button handlers.
5
+ */
6
+
7
+ let nextId = 0;
8
+
9
+ export const toastStore = $state({ items: [] });
10
+
11
+ /**
12
+ * Push a toast. Returns the toast id so the caller can dismiss early.
13
+ *
14
+ * @param {string} message
15
+ * @param {{ variant?: 'info' | 'success' | 'warning' | 'error', duration?: number }} [opts]
16
+ * `duration` in ms, default 4000. Set to 0 for sticky.
17
+ */
18
+ export function toast(message, opts = {}) {
19
+ const id = ++nextId;
20
+ const item = {
21
+ id,
22
+ message,
23
+ variant: opts.variant ?? 'info',
24
+ duration: opts.duration ?? 4000
25
+ };
26
+ toastStore.items.push(item);
27
+ if (item.duration > 0) {
28
+ setTimeout(() => dismiss(id), item.duration);
29
+ }
30
+ return id;
31
+ }
32
+
33
+ export const notify = toast;
34
+
35
+ export function dismiss(id) {
36
+ const i = toastStore.items.findIndex((t) => t.id === id);
37
+ if (i >= 0) toastStore.items.splice(i, 1);
38
+ }
39
+
40
+ export function clear() {
41
+ toastStore.items.length = 0;
42
+ }
@@ -0,0 +1,55 @@
1
+ span(class!="{classes}" bind:this!="{el}")
2
+ | {display}
3
+
4
+ <script>
5
+ import { onMount } from 'svelte'
6
+ import { cn } from '@human-synthesis/norns-ui/cn'
7
+
8
+ {
9
+ value = 0
10
+ from = 0
11
+ duration = 0.9
12
+ decimals = 0
13
+ format
14
+ class: extra = ''
15
+ } := $props()
16
+
17
+ display .= $state String((from ?? value).toFixed(decimals))
18
+ el .= $state null
19
+ hasMounted .= $state false
20
+
21
+ classes := cn 'tabular-nums', extra
22
+
23
+ doFormat := (n) =>
24
+ if format
25
+ format(n)
26
+ else if decimals === 0
27
+ Math.round(n).toLocaleString()
28
+ else
29
+ n.toFixed(decimals)
30
+
31
+ $effect =>
32
+ return unless hasMounted
33
+ // Re-runs whenever `value` changes (after mount).
34
+ v := value
35
+ (async =>
36
+ { animate } := await import('motion')
37
+ anim := animate from, v, {
38
+ duration
39
+ onUpdate: (latest) => display = doFormat(latest)
40
+ onComplete: => display = doFormat(v)
41
+ }
42
+ anim
43
+ )()
44
+
45
+ onMount =>
46
+ hasMounted = true
47
+ (async =>
48
+ { animate } := await import('motion')
49
+ animate (from ?? 0), value, {
50
+ duration
51
+ onUpdate: (latest) => display = doFormat(latest)
52
+ onComplete: => display = doFormat(value)
53
+ }
54
+ )()
55
+ </script>
@@ -0,0 +1,25 @@
1
+ .gradient-bg(class!="{classes}" style!="{styleStr}")
2
+ +if('children')
3
+ .relative
4
+ | {@render children()}
5
+
6
+ <script>
7
+ import { cn } from '@human-synthesis/norns-ui/cn'
8
+
9
+ {
10
+ colors = [
11
+ 'oklch(60% 0.25 290)'
12
+ 'oklch(60% 0.18 240)'
13
+ 'oklch(70% 0.18 200)'
14
+ 'oklch(60% 0.25 320)'
15
+ ]
16
+ duration = 18
17
+ angle = 130
18
+ children
19
+ class: extra = ''
20
+ } := $props()
21
+
22
+ classes := cn 'gradient-bg', extra
23
+ stops := $derived colors.join ', '
24
+ styleStr := $derived `--gradient-bg-stops: ${stops}; --gradient-bg-angle: ${angle}deg; --gradient-bg-duration: ${duration}s`
25
+ </script>
@@ -0,0 +1,48 @@
1
+ button(
2
+ type!="{type}"
3
+ class!="{classes}"
4
+ disabled!="{disabled}"
5
+ onclick!="{onclick}"
6
+ bind:this!="{el}"
7
+ )
8
+ span.liquid-btn-blob(aria-hidden="true")
9
+ span.liquid-btn-content
10
+ +if('icon')
11
+ Icon(name!="{icon}" size!="{iconSize}")
12
+ +if('children')
13
+ | {@render children()}
14
+
15
+ <script>
16
+ import { onMount } from 'svelte'
17
+ import { cn } from '@human-synthesis/norns-ui/cn'
18
+ import Icon from './../components/Icon.n'
19
+
20
+ {
21
+ variant = 'primary'
22
+ size = 'md'
23
+ type = 'button'
24
+ disabled = false
25
+ onclick
26
+ icon
27
+ children
28
+ class: extra = ''
29
+ } := $props()
30
+
31
+ iconSize := size === 'sm' ? 'size-3.5' : size === 'lg' ? 'size-5' : 'size-4'
32
+
33
+ classes := cn 'btn', `btn-${variant}`, size !== 'md' && `btn-${size}`, 'liquid-btn', extra
34
+
35
+ el .= $state null
36
+
37
+ onMount =>
38
+ return unless el
39
+ (async =>
40
+ { animate } := await import('motion')
41
+ blob := el.querySelector '.liquid-btn-blob'
42
+ return unless blob
43
+ el.addEventListener 'mouseenter', =>
44
+ animate blob, { transform: ['scale(0.6)', 'scale(1.4)'] }, { duration: 0.6, easing: [0.34, 1.56, 0.64, 1] }
45
+ el.addEventListener 'mouseleave', =>
46
+ animate blob, { transform: 'scale(0.6)' }, { duration: 0.4 }
47
+ )()
48
+ </script>
@@ -0,0 +1,37 @@
1
+ div(class!="{classes}" style!="{initialStyle}" bind:this!="{el}")
2
+ | {@render children?.()}
3
+
4
+ <script>
5
+ import { onMount } from 'svelte'
6
+ import { cn } from '@human-synthesis/norns-ui/cn'
7
+
8
+ {
9
+ direction = 'up'
10
+ distance = 12
11
+ duration = 0.5
12
+ delay = 0
13
+ once = true
14
+ threshold = 0.15
15
+ children
16
+ class: extra = ''
17
+ } := $props()
18
+
19
+ classes := cn 'will-change-transform', extra
20
+
21
+ axis := direction === 'left' || direction === 'right' ? 'X' : 'Y'
22
+ sign := direction === 'down' || direction === 'right' ? -distance : distance
23
+
24
+ initialStyle := `opacity: 0; transform: translate${axis}(${sign}px)`
25
+
26
+ el .= $state null
27
+
28
+ onMount =>
29
+ return unless el
30
+ (async =>
31
+ { inView, animate } := await import('motion')
32
+ inView el, =>
33
+ animate el, { opacity: [0, 1], [`transform`]: [`translate${axis}(${sign}px)`, `translate${axis}(0)`] }, { duration, delay }
34
+ once ? false : (=> animate(el, { opacity: 0 }, { duration: 0 }))
35
+ , { amount: threshold }
36
+ )()
37
+ </script>
@@ -0,0 +1,53 @@
1
+ .sparkles-wrap(class!="{classes}" bind:this!="{wrap}")
2
+ +if('children')
3
+ | {@render children()}
4
+ .sparkles-overlay(aria-hidden="true")
5
+ +each('seeds as s')
6
+ span.sparkle(style!="{`left: ${s.x}%; top: ${s.y}%; width: ${s.size}px; height: ${s.size}px; --sparkle-color: ${s.color}; animation-delay: ${s.delay}s; animation-duration: ${s.duration}s`}")
7
+
8
+ <script>
9
+ import { onMount, onDestroy } from 'svelte'
10
+ import { cn } from '@human-synthesis/norns-ui/cn'
11
+
12
+ {
13
+ density = 14
14
+ colors = ['var(--color-primary-400)', 'var(--color-info-400)', 'var(--color-warning-400)']
15
+ minSize = 4
16
+ maxSize = 10
17
+ children
18
+ class: extra = ''
19
+ } := $props()
20
+
21
+ classes := cn 'sparkles-wrap', extra
22
+
23
+ rand := (min, max) => min + Math.random() * (max - min)
24
+
25
+ seeds := $derived.by =>
26
+ out := []
27
+ i .= 0
28
+ while i < density
29
+ out.push {
30
+ x: rand(2, 96)
31
+ y: rand(2, 96)
32
+ size: Math.round rand(minSize, maxSize)
33
+ color: colors[i % colors.length]
34
+ delay: rand(0, 3)
35
+ duration: rand(1.6, 3.2)
36
+ }
37
+ i++
38
+ out
39
+
40
+ wrap .= $state null
41
+ stopObserver .= $state null
42
+
43
+ onMount =>
44
+ return unless wrap
45
+ // Pause CSS animations off-screen via animation-play-state.
46
+ io := new IntersectionObserver (entries) =>
47
+ for entry of entries
48
+ wrap.classList.toggle 'sparkles-paused', !entry.isIntersecting
49
+ io.observe wrap
50
+ stopObserver = => io.disconnect()
51
+
52
+ onDestroy => stopObserver?.()
53
+ </script>
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `@human-synthesis/norns-ui/motion` — opt-in motion subpath.
3
+ *
4
+ * Importing from this path pulls in [Motion One](https://motion.dev/) (~3 KB
5
+ * gzipped). The default barrel at the package root stays motion-free; if you
6
+ * never import from `/motion` your bundle stays unaffected.
7
+ *
8
+ * Auto-import (via `presetUI()`) deliberately does NOT register these names —
9
+ * we don't want every page to pay the Motion One cost. Import explicitly:
10
+ *
11
+ * import AnimatedNumber from '@human-synthesis/norns-ui/motion/AnimatedNumber';
12
+ * import Reveal from '@human-synthesis/norns-ui/motion/Reveal';
13
+ */
14
+ export { default as AnimatedNumber } from './AnimatedNumber.n';
15
+ export { default as Reveal } from './Reveal.n';
16
+ export { default as LiquidButton } from './LiquidButton.n';
17
+ export { default as Sparkles } from './Sparkles.n';
18
+ export { default as GradientBackground } from './GradientBackground.n';