@inglorious/ui 8.3.1 → 8.4.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 (88) hide show
  1. package/package.json +9 -9
  2. package/src/controls/button/button.stories.js +1 -1
  3. package/src/controls/button/template.js +1 -1
  4. package/src/controls/button-group/button-group.stories.js +1 -1
  5. package/src/controls/button-group/template.js +1 -1
  6. package/src/controls/checkbox/checkbox.stories.js +1 -1
  7. package/src/controls/checkbox/style.css +1 -1
  8. package/src/controls/checkbox/template.js +7 -5
  9. package/src/controls/combobox/combobox.stories.js +1 -1
  10. package/src/controls/combobox/template.js +16 -11
  11. package/src/controls/fab/fab.stories.js +1 -1
  12. package/src/controls/file-upload/file-upload.stories.js +1 -1
  13. package/src/controls/file-upload/template.js +18 -7
  14. package/src/controls/icon-button/icon-button.stories.js +1 -1
  15. package/src/controls/image-cropper/image-cropper.stories.js +1 -1
  16. package/src/controls/input/input.stories.js +1 -1
  17. package/src/controls/input/template.js +16 -8
  18. package/src/controls/radio-group/radio-group.stories.js +1 -1
  19. package/src/controls/radio-group/template.js +8 -6
  20. package/src/controls/rating/rating.stories.js +1 -1
  21. package/src/controls/select/select.stories.js +1 -1
  22. package/src/controls/select/template.js +48 -46
  23. package/src/controls/slider/slider.stories.js +1 -1
  24. package/src/controls/slider/template.js +6 -4
  25. package/src/controls/switch/switch.stories.js +1 -1
  26. package/src/controls/switch/template.js +6 -4
  27. package/src/controls/textarea/template.js +17 -6
  28. package/src/controls/textarea/textarea.stories.js +1 -1
  29. package/src/data-display/avatar/avatar.stories.js +1 -1
  30. package/src/data-display/badge/badge.stories.js +1 -1
  31. package/src/data-display/before-after/before-after.stories.js +1 -1
  32. package/src/data-display/carousel/carousel.stories.js +10 -9
  33. package/src/data-display/chip/chip.stories.js +1 -1
  34. package/src/data-display/data-grid/data-grid.stories.js +11 -11
  35. package/src/data-display/divider/divider.stories.js +1 -1
  36. package/src/data-display/icon/icon-utf8.stories.js +1 -1
  37. package/src/data-display/icon/icon.stories.js +1 -1
  38. package/src/data-display/icon/template.js +1 -1
  39. package/src/data-display/list/list.stories.js +1 -1
  40. package/src/data-display/list/template.js +1 -1
  41. package/src/data-display/table/table.stories.js +1 -1
  42. package/src/data-display/table/template.js +1 -1
  43. package/src/data-display/tooltip/template.js +1 -1
  44. package/src/data-display/tooltip/tooltip.stories.js +1 -1
  45. package/src/data-display/typography/template.js +1 -1
  46. package/src/data-display/typography/typography.stories.js +1 -1
  47. package/src/data-display/virtual-list/template.js +21 -21
  48. package/src/examples/dashboard/before-after-data.js +17 -14
  49. package/src/examples/dashboard/dashboard.stories.js +1 -1
  50. package/src/examples/dashboard/primitive-content.js +32 -30
  51. package/src/examples/dashboard/theme-utils.js +5 -5
  52. package/src/feedback/alert/alert.stories.js +1 -1
  53. package/src/feedback/alert/template.js +1 -1
  54. package/src/feedback/backdrop/backdrop.stories.js +1 -1
  55. package/src/feedback/dialog/dialog.stories.js +1 -1
  56. package/src/feedback/progress/progress.stories.js +1 -1
  57. package/src/feedback/progress/template.js +4 -4
  58. package/src/feedback/skeleton/skeleton.stories.js +1 -1
  59. package/src/feedback/snackbar/snackbar.stories.js +1 -1
  60. package/src/layout/container/container.stories.js +1 -1
  61. package/src/layout/container/template.js +1 -1
  62. package/src/layout/flex/flex.stories.js +1 -1
  63. package/src/layout/flex/template.js +1 -1
  64. package/src/layout/grid/grid.stories.js +1 -1
  65. package/src/navigation/bottom-navigation/bottom-navigation.stories.js +1 -1
  66. package/src/navigation/bottom-navigation/template.js +1 -1
  67. package/src/navigation/breadcrumbs/breadcrumbs.stories.js +1 -1
  68. package/src/navigation/breadcrumbs/template.js +1 -1
  69. package/src/navigation/drawer/drawer.stories.js +1 -1
  70. package/src/navigation/link/link.stories.js +1 -1
  71. package/src/navigation/link/template.js +1 -1
  72. package/src/navigation/menu/menu.stories.js +1 -1
  73. package/src/navigation/menu/template.js +1 -1
  74. package/src/navigation/pagination/pagination.stories.js +1 -1
  75. package/src/navigation/speed-dial/speed-dial.stories.js +1 -1
  76. package/src/navigation/stepper/stepper.stories.js +1 -1
  77. package/src/navigation/tabs/tabs.stories.js +1 -1
  78. package/src/shared/fallback-label.js +18 -0
  79. package/src/surfaces/accordion/accordion.stories.js +1 -1
  80. package/src/surfaces/accordion/template.js +1 -1
  81. package/src/surfaces/app-bar/app-bar.stories.js +1 -1
  82. package/src/surfaces/app-bar/template.js +1 -1
  83. package/src/surfaces/card/card.stories.js +1 -1
  84. package/src/surfaces/card/template.js +1 -1
  85. package/src/surfaces/paper/paper.stories.js +1 -1
  86. package/src/surfaces/paper/template.js +1 -1
  87. package/src/shared/{applyElementProps.js → apply-element-props.js} +27 -27
  88. /package/src/stories/{notifyStory.js → notify-story.js} +0 -0
@@ -3,11 +3,12 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
+ import { fallbackLabel } from "../../shared/fallback-label.js"
11
12
 
12
13
  const DEFAULT_VALUE = 0
13
14
  const DEFAULT_MIN = 0
@@ -53,7 +54,7 @@ export function render(props) {
53
54
  html`<div class="iw-slider-header">
54
55
  ${
55
56
  label
56
- ? html`<label for=${inputId}>${label}</label>`
57
+ ? html`<label for=${inputId || nothing}>${label}</label>`
57
58
  : html`<span></span>`
58
59
  }
59
60
  ${
@@ -64,8 +65,9 @@ export function render(props) {
64
65
  </div>`
65
66
  }
66
67
  <input
67
- id=${inputId}
68
+ id=${inputId || nothing}
68
69
  class="iw-slider-input"
70
+ aria-label=${fallbackLabel(inputId, label)}
69
71
  type="range"
70
72
  name=${name}
71
73
  min=${min}
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Switch } from "."
3
3
 
4
4
  export default {
@@ -3,11 +3,11 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
11
 
12
12
  /**
13
13
  * Renders a toggle switch backed by a checkbox input.
@@ -29,6 +29,8 @@ export function render(props) {
29
29
  ...rest
30
30
  } = props
31
31
 
32
+ // The label wraps the input, which is what ties the two together: it needs no
33
+ // `for`, and an empty one would point at nothing and break the click-through.
32
34
  const inputId = id || name
33
35
 
34
36
  const classes = {
@@ -39,9 +41,9 @@ export function render(props) {
39
41
  }
40
42
 
41
43
  return html`
42
- <label class=${classMap(classes)} for=${inputId}>
44
+ <label class=${classMap(classes)}>
43
45
  <input
44
- id=${inputId}
46
+ id=${inputId || nothing}
45
47
  class="iw-switch-input"
46
48
  type="checkbox"
47
49
  name=${name}
@@ -3,11 +3,12 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
+ import { fallbackLabel } from "../../shared/fallback-label.js"
11
12
 
12
13
  /**
13
14
  * Renders a labeled textarea field with optional hint and error messaging.
@@ -39,6 +40,7 @@ export function render(props) {
39
40
  } = props
40
41
 
41
42
  const textareaId = id || name
43
+ const messageId = (error || hint) && id ? `${id}-message` : ""
42
44
 
43
45
  const wrapperClasses = {
44
46
  "iw-textarea-field": true,
@@ -60,7 +62,7 @@ export function render(props) {
60
62
  ${
61
63
  label
62
64
  ? html`
63
- <label for=${textareaId} class="iw-textarea-label">
65
+ <label for=${textareaId || nothing} class="iw-textarea-label">
64
66
  ${label}
65
67
  ${
66
68
  isRequired
@@ -73,8 +75,11 @@ export function render(props) {
73
75
  }
74
76
 
75
77
  <textarea
76
- id=${textareaId}
78
+ id=${textareaId || nothing}
77
79
  name=${name}
80
+ aria-label=${fallbackLabel(textareaId, label)}
81
+ aria-describedby=${messageId || nothing}
82
+ aria-invalid=${error ? "true" : "false"}
78
83
  rows=${rows}
79
84
  .value=${value}
80
85
  placeholder=${placeholder}
@@ -90,9 +95,15 @@ export function render(props) {
90
95
 
91
96
  ${
92
97
  error
93
- ? html`<span class="iw-textarea-error-message">${error}</span>`
98
+ ? html`<span
99
+ id=${messageId || nothing}
100
+ class="iw-textarea-error-message"
101
+ >${error}</span
102
+ >`
94
103
  : hint
95
- ? html`<span class="iw-textarea-hint">${hint}</span>`
104
+ ? html`<span id=${messageId || nothing} class="iw-textarea-hint"
105
+ >${hint}</span
106
+ >`
96
107
  : null
97
108
  }
98
109
  </div>
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Textarea } from "."
3
3
 
4
4
  export default {
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Avatar } from "."
3
3
 
4
4
  export default {
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Badge } from "."
3
3
 
4
4
  export default {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createEntityRender,
3
3
  notifyActionArgType,
4
- } from "../../stories/notifyStory.js"
4
+ } from "../../stories/notify-story.js"
5
5
  import { BeforeAfter } from "./index.js"
6
6
 
7
7
  const before = {
@@ -3,19 +3,11 @@ import { html } from "@inglorious/web"
3
3
  import {
4
4
  createEntityRender,
5
5
  notifyActionArgType,
6
- } from "../../stories/notifyStory.js"
6
+ } from "../../stories/notify-story.js"
7
7
  import { Carousel } from "./index.js"
8
8
 
9
9
  const COLORS = ["#22d3ee", "#4f46e5", "#f59e0b", "#10b981", "#ef4444"]
10
10
 
11
- const slide = (index) =>
12
- html`<div
13
- style="display:grid;place-items:center;height:14rem;border-radius:0.5rem;
14
- background:${COLORS[index]};color:#fff;font:700 2rem sans-serif;"
15
- >
16
- ${index + 1}
17
- </div>`
18
-
19
11
  const items = COLORS.map((color, index) => slide(index))
20
12
 
21
13
  export default {
@@ -164,3 +156,12 @@ ManyPerView.args = {
164
156
  ManyPerView.decorators = [
165
157
  (story) => html`<div style="--iw-carousel-item-size: 14rem">${story()}</div>`,
166
158
  ]
159
+
160
+ function slide(index) {
161
+ return html`<div
162
+ style="display:grid;place-items:center;height:14rem;border-radius:0.5rem;
163
+ background:${COLORS[index]};color:#fff;font:700 2rem sans-serif;"
164
+ >
165
+ ${index + 1}
166
+ </div>`
167
+ }
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Chip } from "."
3
3
 
4
4
  export default {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createEntityRender,
3
3
  notifyActionArgType,
4
- } from "../../stories/notifyStory.js"
4
+ } from "../../stories/notify-story.js"
5
5
  import { DataGrid } from "."
6
6
 
7
7
  const baseRows = [
@@ -44,16 +44,6 @@ const baseColumns = [
44
44
  },
45
45
  ]
46
46
 
47
- function createRows(count) {
48
- return Array.from({ length: count }, (_, index) => ({
49
- id: index + 1,
50
- name: `User ${index + 1}`,
51
- age: 20 + (index % 35),
52
- active: index % 3 !== 0,
53
- role: index % 4 === 0 ? "Admin" : "User",
54
- }))
55
- }
56
-
57
47
  export default {
58
48
  title: "Data Display/DataGrid",
59
49
  tags: ["autodocs"],
@@ -156,3 +146,13 @@ export const Virtualized = {
156
146
  },
157
147
  },
158
148
  }
149
+
150
+ function createRows(count) {
151
+ return Array.from({ length: count }, (_, index) => ({
152
+ id: index + 1,
153
+ name: `User ${index + 1}`,
154
+ age: 20 + (index % 35),
155
+ active: index % 3 !== 0,
156
+ role: index % 4 === 0 ? "Admin" : "User",
157
+ }))
158
+ }
@@ -1,6 +1,6 @@
1
1
  import { render } from "@inglorious/web/test"
2
2
 
3
- import { createRender } from "../../stories/notifyStory.js"
3
+ import { createRender } from "../../stories/notify-story.js"
4
4
  import { Divider } from "."
5
5
 
6
6
  export default {
@@ -6,7 +6,7 @@ import { Button } from "../../controls/button"
6
6
  import {
7
7
  createEntityRender,
8
8
  notifyActionArgType,
9
- } from "../../stories/notifyStory.js"
9
+ } from "../../stories/notify-story.js"
10
10
  import { Icon } from "."
11
11
 
12
12
  const UnicodeList = {
@@ -4,7 +4,7 @@ import arrowBack from "@iconify-icons/material-symbols/arrow-back"
4
4
  import settingsFilled from "@iconify-icons/material-symbols/settings"
5
5
  import settingsOutline from "@iconify-icons/material-symbols/settings-outline"
6
6
 
7
- import { createRender } from "../../stories/notifyStory.js"
7
+ import { createRender } from "../../stories/notify-story.js"
8
8
  import { Icon } from "."
9
9
 
10
10
  export default {
@@ -9,7 +9,7 @@ import { classMap } from "@inglorious/web/directives/class-map"
9
9
  import { ref } from "@inglorious/web/directives/ref"
10
10
  import { unsafeSVG } from "@inglorious/web/directives/unsafe-svg"
11
11
 
12
- import { applyElementProps } from "../../shared/applyElementProps.js"
12
+ import { applyElementProps } from "../../shared/apply-element-props.js"
13
13
 
14
14
  /**
15
15
  * Renders an inline icon with size and color control.
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { List } from "."
3
3
 
4
4
  export default {
@@ -28,7 +28,7 @@ import { when } from "@inglorious/web/directives/when"
28
28
  import { IconButton } from "../../controls/icon-button"
29
29
  import { Icon } from "../../data-display/icon"
30
30
  import { Flex } from "../../layout/flex"
31
- import { applyElementProps } from "../../shared/applyElementProps.js"
31
+ import { applyElementProps } from "../../shared/apply-element-props.js"
32
32
 
33
33
  const PRETTY_INDEX = 1
34
34
 
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Table } from "."
3
3
 
4
4
  export default {
@@ -9,7 +9,7 @@ import { classMap } from "@inglorious/web/directives/class-map"
9
9
  import { ref } from "@inglorious/web/directives/ref"
10
10
  import { repeat } from "@inglorious/web/directives/repeat"
11
11
 
12
- import { applyElementProps } from "../../shared/applyElementProps.js"
12
+ import { applyElementProps } from "../../shared/apply-element-props.js"
13
13
 
14
14
  const EVEN_ROW_DIVISOR = 2
15
15
  const STRIPED_OFFSET = 1
@@ -7,7 +7,7 @@ import { html } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
11
 
12
12
  /**
13
13
  * Renders a tooltip trigger and bubble with positional styling.
@@ -1,6 +1,6 @@
1
1
  import { html } from "@inglorious/web"
2
2
 
3
- import { createRender } from "../../stories/notifyStory.js"
3
+ import { createRender } from "../../stories/notify-story.js"
4
4
  import { Tooltip } from "."
5
5
 
6
6
  export default {
@@ -7,7 +7,7 @@ import { html } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
11
 
12
12
  /**
13
13
  * Renders styled text with semantic variants such as headings, body, and caption.
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Typography } from "."
3
3
 
4
4
  export default {
@@ -15,27 +15,6 @@ const PRETTY_INDEX = 1
15
15
  // measuring is an update, so measuring on each render would loop forever.
16
16
  const measured = new WeakSet()
17
17
 
18
- /**
19
- * Notifies `mount` once per list element, after a frame and once it is in the
20
- * document: before that it has no layout to measure.
21
- * @param {HTMLElement} el
22
- * @param {VirtualListEntity} entity
23
- * @param {Api} api
24
- */
25
- function measureOnce(el, entity, api) {
26
- if (measured.has(el)) return
27
- measured.add(el)
28
-
29
- const measure = () => {
30
- if (!el.isConnected) {
31
- requestAnimationFrame(measure)
32
- return
33
- }
34
- api.notify(`#${entity.id}:mount`, el)
35
- }
36
- requestAnimationFrame(measure)
37
- }
38
-
39
18
  /**
40
19
  * Renders a virtualized list that only mounts visible items for performance.
41
20
  * Uses item height estimates to compute scroll ranges and notifies on mount/scroll.
@@ -125,3 +104,24 @@ export function renderItem(entity, { item, index }, api) {
125
104
  ${index + PRETTY_INDEX}. ${JSON.stringify(item)}
126
105
  </div>`
127
106
  }
107
+
108
+ /**
109
+ * Notifies `mount` once per list element, after a frame and once it is in the
110
+ * document: before that it has no layout to measure.
111
+ * @param {HTMLElement} el
112
+ * @param {VirtualListEntity} entity
113
+ * @param {Api} api
114
+ */
115
+ function measureOnce(el, entity, api) {
116
+ if (measured.has(el)) return
117
+ measured.add(el)
118
+
119
+ const measure = () => {
120
+ if (!el.isConnected) {
121
+ requestAnimationFrame(measure)
122
+ return
123
+ }
124
+ api.notify(`#${entity.id}:mount`, el)
125
+ }
126
+ requestAnimationFrame(measure)
127
+ }
@@ -1,10 +1,22 @@
1
+ export const beforeAfterImages = {
2
+ before: {
3
+ src: svg("BEFORE", "#9ca3af", "#374151"),
4
+ alt: "Before — grayscale",
5
+ },
6
+ after: {
7
+ src: svg("AFTER", "#22d3ee", "#4f46e5"),
8
+ alt: "After — color graded",
9
+ },
10
+ }
11
+
1
12
  // Self-contained demo images for the Before/After control, so the dashboard
2
13
  // renders the comparison without any network requests.
3
14
 
4
- const svg = (label, from, to) =>
5
- "data:image/svg+xml," +
6
- encodeURIComponent(
7
- `<svg xmlns="http://www.w3.org/2000/svg" width="960" height="540" viewBox="0 0 960 540">
15
+ function svg(label, from, to) {
16
+ return (
17
+ "data:image/svg+xml," +
18
+ encodeURIComponent(
19
+ `<svg xmlns="http://www.w3.org/2000/svg" width="960" height="540" viewBox="0 0 960 540">
8
20
  <defs>
9
21
  <linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
10
22
  <stop offset="0" stop-color="${from}"/>
@@ -15,15 +27,6 @@ const svg = (label, from, to) =>
15
27
  <text x="48" y="496" font-family="sans-serif" font-size="72" font-weight="700"
16
28
  fill="rgba(255,255,255,0.92)">${label}</text>
17
29
  </svg>`,
30
+ )
18
31
  )
19
-
20
- export const beforeAfterImages = {
21
- before: {
22
- src: svg("BEFORE", "#9ca3af", "#374151"),
23
- alt: "Before — grayscale",
24
- },
25
- after: {
26
- src: svg("AFTER", "#22d3ee", "#4f46e5"),
27
- alt: "After — color graded",
28
- },
29
32
  }
@@ -5,7 +5,7 @@ import { Chart } from "@inglorious/charts"
5
5
  import {
6
6
  createEntityRender,
7
7
  notifyActionArgType,
8
- } from "../../stories/notifyStory.js"
8
+ } from "../../stories/notify-story.js"
9
9
  import { AppDrawer } from "./app-drawer.js"
10
10
  import { AppHeader } from "./app-header.js"
11
11
  import { Dashboard } from "./dashboard.js"
@@ -114,38 +114,8 @@ const categoryMeta = {
114
114
  },
115
115
  }
116
116
 
117
- const previewRow = (children) =>
118
- html`<div class="iw-primitive-preview-row">${children}</div>`
119
-
120
- const previewColumn = (children) =>
121
- html`<div class="iw-primitive-preview-column">${children}</div>`
122
-
123
117
  const livePreviews = new Map()
124
118
 
125
- /**
126
- * Entity-driven primitives render their controls from state, so a preview
127
- * without a store freezes: a carousel arrow would recompute from the same page
128
- * forever, and a dragged divider would never move. Give each one its own store,
129
- * created once and reused on every re-render so the preview keeps its state.
130
- * @param {Object.<string, any>} types
131
- * @param {Object.<string, any>} entity
132
- * @returns {HTMLElement}
133
- */
134
- function livePreview(types, entity) {
135
- if (!livePreviews.has(entity.id)) {
136
- const container = document.createElement("div")
137
- // The mount needs an element, but it must not become a box of its own:
138
- // as a flex item it would shrink and take the primitive down with it.
139
- container.style.display = "contents"
140
-
141
- const store = createStore({ types, entities: { [entity.id]: entity } })
142
- mount(store, (api) => api.render(entity.id), container)
143
- livePreviews.set(entity.id, container)
144
- }
145
-
146
- return livePreviews.get(entity.id)
147
- }
148
-
149
119
  const carouselSlides = [
150
120
  "#22d3ee",
151
121
  "#4f46e5",
@@ -1542,3 +1512,35 @@ function toTitleCase(slug) {
1542
1512
  .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
1543
1513
  .join(" ")
1544
1514
  }
1515
+
1516
+ /**
1517
+ * Entity-driven primitives render their controls from state, so a preview
1518
+ * without a store freezes: a carousel arrow would recompute from the same page
1519
+ * forever, and a dragged divider would never move. Give each one its own store,
1520
+ * created once and reused on every re-render so the preview keeps its state.
1521
+ * @param {Object.<string, any>} types
1522
+ * @param {Object.<string, any>} entity
1523
+ * @returns {HTMLElement}
1524
+ */
1525
+ function livePreview(types, entity) {
1526
+ if (!livePreviews.has(entity.id)) {
1527
+ const container = document.createElement("div")
1528
+ // The mount needs an element, but it must not become a box of its own:
1529
+ // as a flex item it would shrink and take the primitive down with it.
1530
+ container.style.display = "contents"
1531
+
1532
+ const store = createStore({ types, entities: { [entity.id]: entity } })
1533
+ mount(store, (api) => api.render(entity.id), container)
1534
+ livePreviews.set(entity.id, container)
1535
+ }
1536
+
1537
+ return livePreviews.get(entity.id)
1538
+ }
1539
+
1540
+ function previewRow(children) {
1541
+ return html`<div class="iw-primitive-preview-row">${children}</div>`
1542
+ }
1543
+
1544
+ function previewColumn(children) {
1545
+ return html`<div class="iw-primitive-preview-column">${children}</div>`
1546
+ }
@@ -61,6 +61,11 @@ export function nextMode(mode) {
61
61
  return MODE_CYCLE[(index + 1) % MODE_CYCLE.length]
62
62
  }
63
63
 
64
+ export const DEFAULTS = {
65
+ theme: DEFAULT_THEME,
66
+ mode: DEFAULT_MODE,
67
+ }
68
+
64
69
  function resolveMode(mode) {
65
70
  if (mode !== "auto") return mode
66
71
  return getSystemMode()
@@ -88,8 +93,3 @@ function ensureSystemListener() {
88
93
  systemMedia.addListener(systemListener)
89
94
  }
90
95
  }
91
-
92
- export const DEFAULTS = {
93
- theme: DEFAULT_THEME,
94
- mode: DEFAULT_MODE,
95
- }
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Alert } from "."
3
3
 
4
4
  export default {
@@ -7,7 +7,7 @@ import { html } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
10
- import { applyElementProps } from "../../shared/applyElementProps.js"
10
+ import { applyElementProps } from "../../shared/apply-element-props.js"
11
11
 
12
12
  /**
13
13
  * Renders an alert message with optional title, description, icon, and actions.
@@ -1,6 +1,6 @@
1
1
  import { html } from "@inglorious/web"
2
2
 
3
- import { createRender } from "../../stories/notifyStory.js"
3
+ import { createRender } from "../../stories/notify-story.js"
4
4
  import { Backdrop } from "."
5
5
 
6
6
  export default {
@@ -1,6 +1,6 @@
1
1
  import { html } from "@inglorious/web"
2
2
 
3
- import { createRender } from "../../stories/notifyStory.js"
3
+ import { createRender } from "../../stories/notify-story.js"
4
4
  import { Dialog } from "."
5
5
 
6
6
  export default {
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Progress } from "."
3
3
 
4
4
  export default {
@@ -6,10 +6,6 @@
6
6
  import { html } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
 
9
- function clamp(value) {
10
- return Math.max(0, Math.min(100, value))
11
- }
12
-
13
9
  /**
14
10
  * Renders a linear or circular progress indicator.
15
11
  * Indeterminate mode is used when no explicit value is provided.
@@ -90,3 +86,7 @@ export function render(props) {
90
86
  </div>
91
87
  </div>`
92
88
  }
89
+
90
+ function clamp(value) {
91
+ return Math.max(0, Math.min(100, value))
92
+ }
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Skeleton } from "."
3
3
 
4
4
  export default {
@@ -1,4 +1,4 @@
1
- import { createRender } from "../../stories/notifyStory.js"
1
+ import { createRender } from "../../stories/notify-story.js"
2
2
  import { Snackbar } from "."
3
3
 
4
4
  export default {
@@ -1,6 +1,6 @@
1
1
  import { html } from "@inglorious/web"
2
2
 
3
- import { createRender } from "../../stories/notifyStory.js"
3
+ import { createRender } from "../../stories/notify-story.js"
4
4
  import { Container } from "."
5
5
 
6
6
  export default {