@k2b/ui 0.51.0 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/dist/base.css +3 -0
  2. package/dist/browser/actions/Toolbar.js +8 -2
  3. package/dist/browser/actions/Toolbar.js.map +1 -1
  4. package/dist/browser/charts/core/bar-labels.js +5 -0
  5. package/dist/browser/charts/core/bar-labels.js.map +1 -0
  6. package/dist/browser/charts/core/bubble.js +166 -0
  7. package/dist/browser/charts/core/bubble.js.map +1 -0
  8. package/dist/browser/charts/core/default-styles.js +83 -0
  9. package/dist/browser/charts/core/default-styles.js.map +1 -0
  10. package/dist/browser/charts/core/funnel-layout.js +79 -0
  11. package/dist/browser/charts/core/funnel-layout.js.map +1 -0
  12. package/dist/browser/charts/core/funnel.js +27 -0
  13. package/dist/browser/charts/core/funnel.js.map +1 -0
  14. package/dist/browser/charts/core/index.js +6 -1
  15. package/dist/browser/charts/core/index.js.map +1 -1
  16. package/dist/browser/charts/core/pareto.js +120 -0
  17. package/dist/browser/charts/core/pareto.js.map +1 -0
  18. package/dist/browser/charts/core/radar.js +101 -0
  19. package/dist/browser/charts/core/radar.js.map +1 -0
  20. package/dist/browser/charts/core/registry.js +11 -1
  21. package/dist/browser/charts/core/registry.js.map +1 -1
  22. package/dist/browser/charts/core/render-size.js +3 -1
  23. package/dist/browser/charts/core/render-size.js.map +1 -1
  24. package/dist/browser/charts/core/render.js +19 -0
  25. package/dist/browser/charts/core/render.js.map +1 -1
  26. package/dist/browser/charts/core/snapshot.js +1 -1
  27. package/dist/browser/charts/core/snapshot.js.map +1 -1
  28. package/dist/browser/charts/core/svg-barGauge.js +67 -0
  29. package/dist/browser/charts/core/svg-barGauge.js.map +1 -0
  30. package/dist/browser/charts/core/svg-boxplot.js +127 -0
  31. package/dist/browser/charts/core/svg-boxplot.js.map +1 -0
  32. package/dist/browser/charts/core/svg-common.js +1065 -0
  33. package/dist/browser/charts/core/svg-common.js.map +1 -0
  34. package/dist/browser/charts/core/svg-gauge.js +185 -0
  35. package/dist/browser/charts/core/svg-gauge.js.map +1 -0
  36. package/dist/browser/charts/core/svg-heatmap.js +80 -0
  37. package/dist/browser/charts/core/svg-heatmap.js.map +1 -0
  38. package/dist/browser/charts/core/svg-histogram.js +73 -0
  39. package/dist/browser/charts/core/svg-histogram.js.map +1 -0
  40. package/dist/browser/charts/core/svg-renderers.js +9 -1777
  41. package/dist/browser/charts/core/svg-renderers.js.map +1 -1
  42. package/dist/browser/charts/core/svg-scatter.js +114 -0
  43. package/dist/browser/charts/core/svg-scatter.js.map +1 -0
  44. package/dist/browser/charts/core/treemap.js +138 -0
  45. package/dist/browser/charts/core/treemap.js.map +1 -0
  46. package/dist/browser/charts/description.js.map +1 -1
  47. package/dist/browser/content/ChartRoot.js +21 -7
  48. package/dist/browser/content/ChartRoot.js.map +1 -1
  49. package/dist/browser/content/ChartSnapshotView.js +4 -1
  50. package/dist/browser/content/ChartSnapshotView.js.map +1 -1
  51. package/dist/browser/content/DataTable.js +186 -193
  52. package/dist/browser/content/DataTable.js.map +1 -1
  53. package/dist/browser/content/Lightbox.js +55 -23
  54. package/dist/browser/content/Lightbox.js.map +1 -1
  55. package/dist/browser/content/ThumbnailStrip.js +174 -0
  56. package/dist/browser/content/ThumbnailStrip.js.map +1 -0
  57. package/dist/browser/content/chart-bar.js +98 -0
  58. package/dist/browser/content/chart-bar.js.map +1 -1
  59. package/dist/browser/content/chart-inspection-core.js +28 -8
  60. package/dist/browser/content/chart-inspection-core.js.map +1 -1
  61. package/dist/browser/content/chart-message-catalog.js +18 -0
  62. package/dist/browser/content/chart-message-catalog.js.map +1 -1
  63. package/dist/browser/content/index.js +1 -0
  64. package/dist/browser/content/index.js.map +1 -1
  65. package/dist/browser/content/thumbnail-strip-messages.js +24 -0
  66. package/dist/browser/content/thumbnail-strip-messages.js.map +1 -0
  67. package/dist/browser/inputs/ChoiceInputs.js +132 -101
  68. package/dist/browser/inputs/ChoiceInputs.js.map +1 -1
  69. package/dist/browser/inputs/index.js +1 -0
  70. package/dist/browser/inputs/index.js.map +1 -1
  71. package/dist/browser/inputs/markdown/MarkdownSelectionToolbar.js +330 -0
  72. package/dist/browser/inputs/markdown/MarkdownSelectionToolbar.js.map +1 -0
  73. package/dist/browser/internal/field.js +96 -77
  74. package/dist/browser/internal/field.js.map +1 -1
  75. package/dist/browser/layout/AppWorkspace.js +7 -5
  76. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  77. package/dist/browser/layout/PanelDialog.js +92 -68
  78. package/dist/browser/layout/PanelDialog.js.map +1 -1
  79. package/dist/browser/surfaces/StatCell.js +82 -70
  80. package/dist/browser/surfaces/StatCell.js.map +1 -1
  81. package/dist/browser/surfaces/stat-cell-messages.js +4 -2
  82. package/dist/browser/surfaces/stat-cell-messages.js.map +1 -1
  83. package/dist/browser/widgets/DashboardFrame.js +93 -88
  84. package/dist/browser/widgets/DashboardFrame.js.map +1 -1
  85. package/dist/ssr/actions/Toolbar.js +8 -2
  86. package/dist/ssr/actions/Toolbar.js.map +1 -1
  87. package/dist/ssr/charts/core/bar-labels.js +5 -0
  88. package/dist/ssr/charts/core/bar-labels.js.map +1 -0
  89. package/dist/ssr/charts/core/bubble.js +166 -0
  90. package/dist/ssr/charts/core/bubble.js.map +1 -0
  91. package/dist/ssr/charts/core/default-styles.js +83 -0
  92. package/dist/ssr/charts/core/default-styles.js.map +1 -0
  93. package/dist/ssr/charts/core/funnel-layout.js +79 -0
  94. package/dist/ssr/charts/core/funnel-layout.js.map +1 -0
  95. package/dist/ssr/charts/core/funnel.js +27 -0
  96. package/dist/ssr/charts/core/funnel.js.map +1 -0
  97. package/dist/ssr/charts/core/index.js +6 -1
  98. package/dist/ssr/charts/core/index.js.map +1 -1
  99. package/dist/ssr/charts/core/pareto.js +120 -0
  100. package/dist/ssr/charts/core/pareto.js.map +1 -0
  101. package/dist/ssr/charts/core/radar.js +101 -0
  102. package/dist/ssr/charts/core/radar.js.map +1 -0
  103. package/dist/ssr/charts/core/registry.js +11 -1
  104. package/dist/ssr/charts/core/registry.js.map +1 -1
  105. package/dist/ssr/charts/core/render-size.js +3 -1
  106. package/dist/ssr/charts/core/render-size.js.map +1 -1
  107. package/dist/ssr/charts/core/render.js +19 -0
  108. package/dist/ssr/charts/core/render.js.map +1 -1
  109. package/dist/ssr/charts/core/snapshot.js +1 -1
  110. package/dist/ssr/charts/core/snapshot.js.map +1 -1
  111. package/dist/ssr/charts/core/svg-barGauge.js +67 -0
  112. package/dist/ssr/charts/core/svg-barGauge.js.map +1 -0
  113. package/dist/ssr/charts/core/svg-boxplot.js +127 -0
  114. package/dist/ssr/charts/core/svg-boxplot.js.map +1 -0
  115. package/dist/ssr/charts/core/svg-common.js +1065 -0
  116. package/dist/ssr/charts/core/svg-common.js.map +1 -0
  117. package/dist/ssr/charts/core/svg-gauge.js +185 -0
  118. package/dist/ssr/charts/core/svg-gauge.js.map +1 -0
  119. package/dist/ssr/charts/core/svg-heatmap.js +80 -0
  120. package/dist/ssr/charts/core/svg-heatmap.js.map +1 -0
  121. package/dist/ssr/charts/core/svg-histogram.js +73 -0
  122. package/dist/ssr/charts/core/svg-histogram.js.map +1 -0
  123. package/dist/ssr/charts/core/svg-renderers.js +9 -1777
  124. package/dist/ssr/charts/core/svg-renderers.js.map +1 -1
  125. package/dist/ssr/charts/core/svg-scatter.js +114 -0
  126. package/dist/ssr/charts/core/svg-scatter.js.map +1 -0
  127. package/dist/ssr/charts/core/treemap.js +138 -0
  128. package/dist/ssr/charts/core/treemap.js.map +1 -0
  129. package/dist/ssr/charts/description.js.map +1 -1
  130. package/dist/ssr/content/ChartRoot.js +21 -7
  131. package/dist/ssr/content/ChartRoot.js.map +1 -1
  132. package/dist/ssr/content/ChartSnapshotView.js +1 -0
  133. package/dist/ssr/content/ChartSnapshotView.js.map +1 -1
  134. package/dist/ssr/content/DataTable.js +12 -16
  135. package/dist/ssr/content/DataTable.js.map +1 -1
  136. package/dist/ssr/content/Lightbox.js +32 -3
  137. package/dist/ssr/content/Lightbox.js.map +1 -1
  138. package/dist/ssr/content/ThumbnailStrip.js +103 -0
  139. package/dist/ssr/content/ThumbnailStrip.js.map +1 -0
  140. package/dist/ssr/content/chart-bar.js +98 -0
  141. package/dist/ssr/content/chart-bar.js.map +1 -1
  142. package/dist/ssr/content/chart-inspection-core.js +28 -8
  143. package/dist/ssr/content/chart-inspection-core.js.map +1 -1
  144. package/dist/ssr/content/chart-message-catalog.js +18 -0
  145. package/dist/ssr/content/chart-message-catalog.js.map +1 -1
  146. package/dist/ssr/content/index.js +1 -0
  147. package/dist/ssr/content/index.js.map +1 -1
  148. package/dist/ssr/content/thumbnail-strip-messages.js +24 -0
  149. package/dist/ssr/content/thumbnail-strip-messages.js.map +1 -0
  150. package/dist/ssr/inputs/ChoiceInputs.js +55 -40
  151. package/dist/ssr/inputs/ChoiceInputs.js.map +1 -1
  152. package/dist/ssr/inputs/index.js +1 -0
  153. package/dist/ssr/inputs/index.js.map +1 -1
  154. package/dist/ssr/inputs/markdown/MarkdownSelectionToolbar.js +293 -0
  155. package/dist/ssr/inputs/markdown/MarkdownSelectionToolbar.js.map +1 -0
  156. package/dist/ssr/internal/field.js +36 -24
  157. package/dist/ssr/internal/field.js.map +1 -1
  158. package/dist/ssr/layout/AppWorkspace.js +5 -1
  159. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  160. package/dist/ssr/layout/PanelDialog.js +40 -26
  161. package/dist/ssr/layout/PanelDialog.js.map +1 -1
  162. package/dist/ssr/surfaces/StatCell.js +29 -18
  163. package/dist/ssr/surfaces/StatCell.js.map +1 -1
  164. package/dist/ssr/surfaces/stat-cell-messages.js +4 -2
  165. package/dist/ssr/surfaces/stat-cell-messages.js.map +1 -1
  166. package/dist/ssr/widgets/DashboardFrame.js +6 -11
  167. package/dist/ssr/widgets/DashboardFrame.js.map +1 -1
  168. package/dist/styles.css +1 -1
  169. package/dist/types/actions/Toolbar.d.ts +2 -0
  170. package/dist/types/charts/core/bar-labels.d.ts +1 -0
  171. package/dist/types/charts/core/bubble.d.ts +66 -0
  172. package/dist/types/charts/core/default-styles.d.ts +1 -0
  173. package/dist/types/charts/core/funnel-layout.d.ts +43 -0
  174. package/dist/types/charts/core/funnel.d.ts +13 -0
  175. package/dist/types/charts/core/index.d.ts +6 -1
  176. package/dist/types/charts/core/pareto.d.ts +40 -0
  177. package/dist/types/charts/core/radar.d.ts +47 -0
  178. package/dist/types/charts/core/registry.d.ts +10 -0
  179. package/dist/types/charts/core/render-size.d.ts +1 -1
  180. package/dist/types/charts/core/svg-barGauge.d.ts +3 -0
  181. package/dist/types/charts/core/svg-boxplot.d.ts +18 -0
  182. package/dist/types/charts/core/svg-common.d.ts +612 -0
  183. package/dist/types/charts/core/svg-gauge.d.ts +6 -0
  184. package/dist/types/charts/core/svg-heatmap.d.ts +6 -0
  185. package/dist/types/charts/core/svg-histogram.d.ts +16 -0
  186. package/dist/types/charts/core/svg-renderers.d.ts +8 -612
  187. package/dist/types/charts/core/svg-scatter.d.ts +23 -0
  188. package/dist/types/charts/core/treemap.d.ts +45 -0
  189. package/dist/types/charts/description.d.ts +63 -0
  190. package/dist/types/content/ChartRoot.d.ts +1 -1
  191. package/dist/types/content/Lightbox.d.ts +2 -0
  192. package/dist/types/content/ThumbnailStrip.d.ts +29 -0
  193. package/dist/types/content/chart-bar.d.ts +38 -2
  194. package/dist/types/content/chart-inspection-core.d.ts +7 -0
  195. package/dist/types/content/chart-inspection.d.ts +1 -0
  196. package/dist/types/content/chart-message-catalog.d.ts +8 -0
  197. package/dist/types/content/index.d.ts +1 -0
  198. package/dist/types/content/thumbnail-strip-messages.d.ts +10 -0
  199. package/dist/types/inputs/ChoiceInputs.d.ts +2 -0
  200. package/dist/types/inputs/index.d.ts +2 -0
  201. package/dist/types/inputs/markdown/MarkdownSelectionToolbar.d.ts +19 -0
  202. package/dist/types/internal/field.d.ts +2 -0
  203. package/dist/types/layout/PanelDialog.d.ts +5 -0
  204. package/dist/types/surfaces/stat-cell-messages.d.ts +1 -0
  205. package/dist/types/widgets/DashboardFrame.d.ts +4 -1
  206. package/package.json +2 -2
@@ -0,0 +1,330 @@
1
+ import { template as _$template } from "solid-js/web";
2
+ import { delegateEvents as _$delegateEvents } from "solid-js/web";
3
+ import { getNextElement as _$getNextElement } from "solid-js/web";
4
+ import { runHydrationEvents as _$runHydrationEvents } from "solid-js/web";
5
+ import { getNextMarker as _$getNextMarker } from "solid-js/web";
6
+ import { insert as _$insert } from "solid-js/web";
7
+ import { use as _$use } from "solid-js/web";
8
+ import { createComponent as _$createComponent } from "solid-js/web";
9
+ var _tmpl$ = /*#__PURE__*/_$template(`<div style=display:contents><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/><!$><!/>`);
10
+ import { i18n } from "@k2b/stdlib";
11
+ import { batch, createEffect, createMemo, createSignal, onCleanup, onMount, Show } from "solid-js";
12
+ import { SelectionToolbar } from "../../actions/SelectionToolbar";
13
+ import { Toolbar } from "../../actions/Toolbar";
14
+ import { useLocale } from "../../intl/locale";
15
+ import { insertLink, toggleBold, toggleBulletList, toggleCode, toggleItalic, toggleNumberedList, toggleQuote } from "./actions";
16
+ import { computeActiveFormats } from "./active-formats";
17
+ const selectionMessages = i18n.define({
18
+ baseLocale: "en",
19
+ messages: {
20
+ en: {
21
+ bold: "Bold",
22
+ italic: "Italic",
23
+ inlineCode: "Inline code",
24
+ link: "Link",
25
+ bulletList: "Bullet list",
26
+ numberedList: "Numbered list",
27
+ quote: "Quote",
28
+ selectionFormatting: "Format selection"
29
+ },
30
+ de: {
31
+ bold: "Fett",
32
+ italic: "Kursiv",
33
+ inlineCode: "Inline-Code",
34
+ link: "Link",
35
+ bulletList: "Aufzählung",
36
+ numberedList: "Nummerierte Liste",
37
+ quote: "Zitat",
38
+ selectionFormatting: "Auswahl formatieren"
39
+ }
40
+ }
41
+ });
42
+ export const checkSelectionMessages = () => selectionMessages.check();
43
+
44
+ /**
45
+ * The box of a text range's first line in the editor's mirrored presentation layer, or nothing when that line is
46
+ * scrolled out of the surface. The layer holds the same text as the textarea, so its text nodes map offsets to places.
47
+ */
48
+ export const textRangeBox = (layer, surface, start, end) => {
49
+ const walker = document.createTreeWalker(layer, 4 /* NodeFilter.SHOW_TEXT */);
50
+ let offset = 0;
51
+ let from;
52
+ let to;
53
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
54
+ const length = node.textContent?.length ?? 0;
55
+ if (!from && start <= offset + length) from = [node, start - offset];
56
+ if (end <= offset + length) {
57
+ to = [node, end - offset];
58
+ break;
59
+ }
60
+ offset += length;
61
+ }
62
+ if (!from || !to) return null;
63
+ const range = document.createRange();
64
+ range.setStart(...from);
65
+ range.setEnd(...to);
66
+ const rects = Array.from(range.getClientRects()).filter(rect => rect.width > 0 || rect.height > 0);
67
+ const first = rects[0];
68
+ if (!first) return null;
69
+ const line = rects.filter(rect => Math.abs(rect.top - first.top) < 4);
70
+ const multiline = line.length < rects.length;
71
+ const right = multiline ? layer.getBoundingClientRect().right : Math.max(...line.map(rect => rect.right));
72
+ const visible = surface.getBoundingClientRect();
73
+ if (first.bottom <= visible.top || first.top >= visible.bottom) return null;
74
+ return new DOMRect(first.left, first.top, Math.max(1, right - first.left), first.height);
75
+ };
76
+ /**
77
+ * A small formatting toolbar that floats above selected text in a `MarkdownEditor`: bold, italic, code, link, lists, and
78
+ * quote. Place it beside an editor with `noToolbar` and pass the editor's textarea. It appears once the pointer lets go
79
+ * of a selection and closes on Escape, a collapsed selection, or when the focus leaves both text and toolbar. Touch
80
+ * devices keep their own selection menu, so nothing of it renders there; the keyboard shortcuts work everywhere. It
81
+ * listens to the textarea itself, so editors without it carry none of its code.
82
+ */
83
+ export function MarkdownSelectionToolbar(props) {
84
+ return _$createComponent(Show, {
85
+ get when() {
86
+ return props.textarea;
87
+ },
88
+ children: textarea => _$createComponent(SelectionFormatting, {
89
+ get textarea() {
90
+ return textarea();
91
+ }
92
+ })
93
+ });
94
+ }
95
+ function SelectionFormatting(props) {
96
+ const locale = useLocale();
97
+ const messages = () => selectionMessages.resolve([locale()]).t;
98
+ const textarea = props.textarea;
99
+ // The editor's surface and its presentation layer: the same text as the textarea, laid out the same way.
100
+ const surface = textarea.parentElement ?? textarea;
101
+ const layer = surface.querySelector(".k2b-markdown-editor__preview") ?? surface;
102
+ const [revision, setRevision] = createSignal(0);
103
+ const bump = () => setRevision(value => value + 1);
104
+ const [finePointer, setFinePointer] = createSignal(false);
105
+ const [dragging, setDragging] = createSignal(false);
106
+ const [textFocused, setTextFocused] = createSignal(document.activeElement === textarea);
107
+ const [toolbarFocused, setToolbarFocused] = createSignal(false);
108
+ const [dismissed, setDismissed] = createSignal();
109
+ let root;
110
+ const selectionKey = () => `${textarea.selectionStart}:${textarea.selectionEnd}`;
111
+ const anchor = () => {
112
+ revision();
113
+ if (textarea.disabled || !finePointer() || dragging() || !(textFocused() || toolbarFocused())) return null;
114
+ if (textarea.selectionStart === textarea.selectionEnd || dismissed() === selectionKey()) return null;
115
+ return textRangeBox(layer, surface, textarea.selectionStart, textarea.selectionEnd);
116
+ };
117
+
118
+ // Escape closes the toolbar for that one selection: a collapsed selection forgets it, so selecting the same words
119
+ // again shows it again.
120
+ createEffect(() => {
121
+ revision();
122
+ if (textarea.selectionStart === textarea.selectionEnd) setDismissed(undefined);
123
+ });
124
+ onMount(() => {
125
+ const query = window.matchMedia("(pointer: coarse)");
126
+ const update = () => setFinePointer(!query.matches);
127
+ update();
128
+ const press = () => {
129
+ setDismissed(undefined);
130
+ setDragging(true);
131
+ const release = () => {
132
+ setDragging(false);
133
+ document.removeEventListener("pointerup", release, true);
134
+ document.removeEventListener("pointercancel", release, true);
135
+ };
136
+ document.addEventListener("pointerup", release, true);
137
+ document.addEventListener("pointercancel", release, true);
138
+ };
139
+ const key = event => {
140
+ if (event.key === "Escape") {
141
+ if (event.defaultPrevented || !anchor()) return;
142
+ event.preventDefault();
143
+ setDismissed(selectionKey());
144
+ return;
145
+ }
146
+ // Selection changes can arrive as one event, so the next key that may select again forgets Escape too.
147
+ if (!["Shift", "Control", "Meta", "Alt"].includes(event.key)) setDismissed(undefined);
148
+ };
149
+ const focus = () => setTextFocused(true);
150
+ const blur = event => batch(() => {
151
+ // Tab into the toolbar keeps it open: the toolbar takes the focus in the same move.
152
+ if (event.relatedTarget instanceof Node && root?.contains(event.relatedTarget)) setToolbarFocused(true);
153
+ setTextFocused(false);
154
+ });
155
+ const selection = () => {
156
+ if (document.activeElement === textarea) bump();
157
+ };
158
+ // The presentation layer renders a frame after an edit; the toolbar measures again once it did.
159
+ const layerElement = layer;
160
+ const layerObserver = new MutationObserver(bump);
161
+ layerObserver.observe(layerElement, {
162
+ childList: true,
163
+ subtree: true,
164
+ characterData: true
165
+ });
166
+ query.addEventListener("change", update);
167
+ textarea.addEventListener("pointerdown", press);
168
+ textarea.addEventListener("keydown", key);
169
+ textarea.addEventListener("focus", focus);
170
+ textarea.addEventListener("blur", blur);
171
+ textarea.addEventListener("input", bump);
172
+ // The toolbar hides while its line is scrolled away and shows again when it returns.
173
+ textarea.addEventListener("scroll", bump);
174
+ document.addEventListener("selectionchange", selection);
175
+ onCleanup(() => {
176
+ layerObserver.disconnect();
177
+ query.removeEventListener("change", update);
178
+ textarea.removeEventListener("pointerdown", press);
179
+ textarea.removeEventListener("keydown", key);
180
+ textarea.removeEventListener("focus", focus);
181
+ textarea.removeEventListener("blur", blur);
182
+ textarea.removeEventListener("input", bump);
183
+ textarea.removeEventListener("scroll", bump);
184
+ document.removeEventListener("selectionchange", selection);
185
+ });
186
+ });
187
+ const run = format => () => format(textarea);
188
+ const formats = createMemo(() => {
189
+ revision();
190
+ return computeActiveFormats(textarea);
191
+ });
192
+ const pressed = format => formats().has(format);
193
+
194
+ // Touch devices keep their own selection menu: the toolbar is not rendered there at all, so nothing of it mounts
195
+ // or animates.
196
+ return _$createComponent(Show, {
197
+ get when() {
198
+ return finePointer();
199
+ },
200
+ get children() {
201
+ return _$createComponent(SelectionToolbar, {
202
+ get label() {
203
+ return messages().selectionFormatting;
204
+ },
205
+ anchor: anchor,
206
+ onEscape: () => {
207
+ setDismissed(selectionKey());
208
+ textarea.focus();
209
+ },
210
+ get children() {
211
+ var _el$ = _$getNextElement(_tmpl$),
212
+ _el$2 = _el$.firstChild,
213
+ [_el$3, _co$] = _$getNextMarker(_el$2.nextSibling),
214
+ _el$4 = _el$3.nextSibling,
215
+ [_el$5, _co$2] = _$getNextMarker(_el$4.nextSibling),
216
+ _el$6 = _el$5.nextSibling,
217
+ [_el$7, _co$3] = _$getNextMarker(_el$6.nextSibling),
218
+ _el$8 = _el$7.nextSibling,
219
+ [_el$9, _co$4] = _$getNextMarker(_el$8.nextSibling),
220
+ _el$0 = _el$9.nextSibling,
221
+ [_el$1, _co$5] = _$getNextMarker(_el$0.nextSibling),
222
+ _el$10 = _el$1.nextSibling,
223
+ [_el$11, _co$6] = _$getNextMarker(_el$10.nextSibling),
224
+ _el$12 = _el$11.nextSibling,
225
+ [_el$13, _co$7] = _$getNextMarker(_el$12.nextSibling),
226
+ _el$14 = _el$13.nextSibling,
227
+ [_el$15, _co$8] = _$getNextMarker(_el$14.nextSibling);
228
+ _el$.$$focusout = event => {
229
+ if (!(event.relatedTarget instanceof Node && event.currentTarget.contains(event.relatedTarget))) setToolbarFocused(false);
230
+ };
231
+ _el$.$$focusin = () => setToolbarFocused(true);
232
+ var _ref$ = root;
233
+ typeof _ref$ === "function" ? _$use(_ref$, _el$) : root = _el$;
234
+ _$insert(_el$, _$createComponent(Toolbar.Action, {
235
+ get label() {
236
+ return messages().bold;
237
+ },
238
+ icon: "ti ti-bold",
239
+ get pressed() {
240
+ return pressed("bold");
241
+ },
242
+ keys: "mod+b",
243
+ get onClick() {
244
+ return run(toggleBold);
245
+ }
246
+ }), _el$3, _co$);
247
+ _$insert(_el$, _$createComponent(Toolbar.Action, {
248
+ get label() {
249
+ return messages().italic;
250
+ },
251
+ icon: "ti ti-italic",
252
+ get pressed() {
253
+ return pressed("italic");
254
+ },
255
+ keys: "mod+i",
256
+ get onClick() {
257
+ return run(toggleItalic);
258
+ }
259
+ }), _el$5, _co$2);
260
+ _$insert(_el$, _$createComponent(Toolbar.Action, {
261
+ get label() {
262
+ return messages().inlineCode;
263
+ },
264
+ icon: "ti ti-code",
265
+ get pressed() {
266
+ return pressed("code");
267
+ },
268
+ keys: "mod+e",
269
+ get onClick() {
270
+ return run(toggleCode);
271
+ }
272
+ }), _el$7, _co$3);
273
+ _$insert(_el$, _$createComponent(Toolbar.Action, {
274
+ get label() {
275
+ return messages().link;
276
+ },
277
+ icon: "ti ti-link",
278
+ keys: "mod+k",
279
+ get onClick() {
280
+ return run(insertLink);
281
+ }
282
+ }), _el$9, _co$4);
283
+ _$insert(_el$, _$createComponent(Toolbar.Separator, {}), _el$1, _co$5);
284
+ _$insert(_el$, _$createComponent(Toolbar.Action, {
285
+ get label() {
286
+ return messages().bulletList;
287
+ },
288
+ icon: "ti ti-list",
289
+ get pressed() {
290
+ return pressed("bullet");
291
+ },
292
+ keys: "mod+shift+8",
293
+ get onClick() {
294
+ return run(toggleBulletList);
295
+ }
296
+ }), _el$11, _co$6);
297
+ _$insert(_el$, _$createComponent(Toolbar.Action, {
298
+ get label() {
299
+ return messages().numberedList;
300
+ },
301
+ icon: "ti ti-list-numbers",
302
+ get pressed() {
303
+ return pressed("ordered");
304
+ },
305
+ keys: "mod+shift+7",
306
+ get onClick() {
307
+ return run(toggleNumberedList);
308
+ }
309
+ }), _el$13, _co$7);
310
+ _$insert(_el$, _$createComponent(Toolbar.Action, {
311
+ get label() {
312
+ return messages().quote;
313
+ },
314
+ icon: "ti ti-quote",
315
+ get pressed() {
316
+ return pressed("quote");
317
+ },
318
+ get onClick() {
319
+ return run(toggleQuote);
320
+ }
321
+ }), _el$15, _co$8);
322
+ _$runHydrationEvents();
323
+ return _el$;
324
+ }
325
+ });
326
+ }
327
+ });
328
+ }
329
+ _$delegateEvents(["focusin", "focusout"]);
330
+ //# sourceMappingURL=MarkdownSelectionToolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["inputs/markdown/MarkdownSelectionToolbar.tsx"],"sourcesContent":["import { i18n } from \"@k2b/stdlib\";\nimport { batch, createEffect, createMemo, createSignal, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { SelectionToolbar } from \"../../actions/SelectionToolbar\";\nimport { Toolbar } from \"../../actions/Toolbar\";\nimport { useLocale } from \"../../intl/locale\";\nimport { insertLink, toggleBold, toggleBulletList, toggleCode, toggleItalic, toggleNumberedList, toggleQuote } from \"./actions\";\nimport { computeActiveFormats } from \"./active-formats\";\n\nconst selectionMessages = i18n.define({\n baseLocale: \"en\",\n messages: {\n en: {\n bold: \"Bold\",\n italic: \"Italic\",\n inlineCode: \"Inline code\",\n link: \"Link\",\n bulletList: \"Bullet list\",\n numberedList: \"Numbered list\",\n quote: \"Quote\",\n selectionFormatting: \"Format selection\",\n },\n de: {\n bold: \"Fett\",\n italic: \"Kursiv\",\n inlineCode: \"Inline-Code\",\n link: \"Link\",\n bulletList: \"Aufzählung\",\n numberedList: \"Nummerierte Liste\",\n quote: \"Zitat\",\n selectionFormatting: \"Auswahl formatieren\",\n },\n },\n});\n\nexport const checkSelectionMessages = () => selectionMessages.check();\n\n/**\n * The box of a text range's first line in the editor's mirrored presentation layer, or nothing when that line is\n * scrolled out of the surface. The layer holds the same text as the textarea, so its text nodes map offsets to places.\n */\nexport const textRangeBox = (layer: HTMLElement, surface: HTMLElement, start: number, end: number): DOMRect | null => {\n const walker = document.createTreeWalker(layer, 4 /* NodeFilter.SHOW_TEXT */);\n let offset = 0;\n let from: [Node, number] | undefined;\n let to: [Node, number] | undefined;\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n const length = node.textContent?.length ?? 0;\n if (!from && start <= offset + length) from = [node, start - offset];\n if (end <= offset + length) {\n to = [node, end - offset];\n break;\n }\n offset += length;\n }\n if (!from || !to) return null;\n const range = document.createRange();\n range.setStart(...from);\n range.setEnd(...to);\n const rects = Array.from(range.getClientRects()).filter((rect) => rect.width > 0 || rect.height > 0);\n const first = rects[0];\n if (!first) return null;\n const line = rects.filter((rect) => Math.abs(rect.top - first.top) < 4);\n const multiline = line.length < rects.length;\n const right = multiline ? layer.getBoundingClientRect().right : Math.max(...line.map((rect) => rect.right));\n const visible = surface.getBoundingClientRect();\n if (first.bottom <= visible.top || first.top >= visible.bottom) return null;\n return new DOMRect(first.left, first.top, Math.max(1, right - first.left), first.height);\n};\n\nexport type MarkdownSelectionToolbarProps = {\n /** The editor's textarea, from `MarkdownEditor`'s `textareaRef`. The toolbar attaches once it is there. */\n textarea: HTMLTextAreaElement | undefined;\n};\n\n/**\n * A small formatting toolbar that floats above selected text in a `MarkdownEditor`: bold, italic, code, link, lists, and\n * quote. Place it beside an editor with `noToolbar` and pass the editor's textarea. It appears once the pointer lets go\n * of a selection and closes on Escape, a collapsed selection, or when the focus leaves both text and toolbar. Touch\n * devices keep their own selection menu, so nothing of it renders there; the keyboard shortcuts work everywhere. It\n * listens to the textarea itself, so editors without it carry none of its code.\n */\nexport function MarkdownSelectionToolbar(props: MarkdownSelectionToolbarProps): JSX.Element {\n return <Show when={props.textarea}>{(textarea) => <SelectionFormatting textarea={textarea()} />}</Show>;\n}\n\nfunction SelectionFormatting(props: { textarea: HTMLTextAreaElement }): JSX.Element {\n const locale = useLocale();\n const messages = () => selectionMessages.resolve([locale()]).t;\n const textarea = props.textarea;\n // The editor's surface and its presentation layer: the same text as the textarea, laid out the same way.\n const surface = textarea.parentElement ?? textarea;\n const layer = surface.querySelector<HTMLElement>(\".k2b-markdown-editor__preview\") ?? surface;\n const [revision, setRevision] = createSignal(0);\n const bump = () => setRevision((value) => value + 1);\n const [finePointer, setFinePointer] = createSignal(false);\n const [dragging, setDragging] = createSignal(false);\n const [textFocused, setTextFocused] = createSignal(document.activeElement === textarea);\n const [toolbarFocused, setToolbarFocused] = createSignal(false);\n const [dismissed, setDismissed] = createSignal<string>();\n let root: HTMLDivElement | undefined;\n\n const selectionKey = () => `${textarea.selectionStart}:${textarea.selectionEnd}`;\n const anchor = () => {\n revision();\n if (textarea.disabled || !finePointer() || dragging() || !(textFocused() || toolbarFocused())) return null;\n if (textarea.selectionStart === textarea.selectionEnd || dismissed() === selectionKey()) return null;\n return textRangeBox(layer, surface, textarea.selectionStart, textarea.selectionEnd);\n };\n\n // Escape closes the toolbar for that one selection: a collapsed selection forgets it, so selecting the same words\n // again shows it again.\n createEffect(() => {\n revision();\n if (textarea.selectionStart === textarea.selectionEnd) setDismissed(undefined);\n });\n\n onMount(() => {\n const query = window.matchMedia(\"(pointer: coarse)\");\n const update = () => setFinePointer(!query.matches);\n update();\n const press = () => {\n setDismissed(undefined);\n setDragging(true);\n const release = () => {\n setDragging(false);\n document.removeEventListener(\"pointerup\", release, true);\n document.removeEventListener(\"pointercancel\", release, true);\n };\n document.addEventListener(\"pointerup\", release, true);\n document.addEventListener(\"pointercancel\", release, true);\n };\n const key = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n if (event.defaultPrevented || !anchor()) return;\n event.preventDefault();\n setDismissed(selectionKey());\n return;\n }\n // Selection changes can arrive as one event, so the next key that may select again forgets Escape too.\n if (![\"Shift\", \"Control\", \"Meta\", \"Alt\"].includes(event.key)) setDismissed(undefined);\n };\n const focus = () => setTextFocused(true);\n const blur = (event: FocusEvent) =>\n batch(() => {\n // Tab into the toolbar keeps it open: the toolbar takes the focus in the same move.\n if (event.relatedTarget instanceof Node && root?.contains(event.relatedTarget)) setToolbarFocused(true);\n setTextFocused(false);\n });\n const selection = () => {\n if (document.activeElement === textarea) bump();\n };\n // The presentation layer renders a frame after an edit; the toolbar measures again once it did.\n const layerElement = layer;\n const layerObserver = new MutationObserver(bump);\n layerObserver.observe(layerElement, { childList: true, subtree: true, characterData: true });\n query.addEventListener(\"change\", update);\n textarea.addEventListener(\"pointerdown\", press);\n textarea.addEventListener(\"keydown\", key);\n textarea.addEventListener(\"focus\", focus);\n textarea.addEventListener(\"blur\", blur);\n textarea.addEventListener(\"input\", bump);\n // The toolbar hides while its line is scrolled away and shows again when it returns.\n textarea.addEventListener(\"scroll\", bump);\n document.addEventListener(\"selectionchange\", selection);\n onCleanup(() => {\n layerObserver.disconnect();\n query.removeEventListener(\"change\", update);\n textarea.removeEventListener(\"pointerdown\", press);\n textarea.removeEventListener(\"keydown\", key);\n textarea.removeEventListener(\"focus\", focus);\n textarea.removeEventListener(\"blur\", blur);\n textarea.removeEventListener(\"input\", bump);\n textarea.removeEventListener(\"scroll\", bump);\n document.removeEventListener(\"selectionchange\", selection);\n });\n });\n\n const run = (format: (textarea: HTMLTextAreaElement) => void) => () => format(textarea);\n const formats = createMemo(() => {\n revision();\n return computeActiveFormats(textarea);\n });\n const pressed = (format: string) => formats().has(format);\n\n // Touch devices keep their own selection menu: the toolbar is not rendered there at all, so nothing of it mounts\n // or animates.\n return (\n <Show when={finePointer()}>\n <SelectionToolbar\n label={messages().selectionFormatting}\n anchor={anchor}\n onEscape={() => {\n setDismissed(selectionKey());\n textarea.focus();\n }}\n >\n <div\n ref={root}\n style={{ display: \"contents\" }}\n onFocusIn={() => setToolbarFocused(true)}\n onFocusOut={(event) => {\n if (!(event.relatedTarget instanceof Node && event.currentTarget.contains(event.relatedTarget))) setToolbarFocused(false);\n }}\n >\n <Toolbar.Action label={messages().bold} icon=\"ti ti-bold\" pressed={pressed(\"bold\")} keys=\"mod+b\" onClick={run(toggleBold)} />\n <Toolbar.Action\n label={messages().italic}\n icon=\"ti ti-italic\"\n pressed={pressed(\"italic\")}\n keys=\"mod+i\"\n onClick={run(toggleItalic)}\n />\n <Toolbar.Action\n label={messages().inlineCode}\n icon=\"ti ti-code\"\n pressed={pressed(\"code\")}\n keys=\"mod+e\"\n onClick={run(toggleCode)}\n />\n <Toolbar.Action label={messages().link} icon=\"ti ti-link\" keys=\"mod+k\" onClick={run(insertLink)} />\n <Toolbar.Separator />\n <Toolbar.Action\n label={messages().bulletList}\n icon=\"ti ti-list\"\n pressed={pressed(\"bullet\")}\n keys=\"mod+shift+8\"\n onClick={run(toggleBulletList)}\n />\n <Toolbar.Action\n label={messages().numberedList}\n icon=\"ti ti-list-numbers\"\n pressed={pressed(\"ordered\")}\n keys=\"mod+shift+7\"\n onClick={run(toggleNumberedList)}\n />\n <Toolbar.Action label={messages().quote} icon=\"ti ti-quote\" pressed={pressed(\"quote\")} onClick={run(toggleQuote)} />\n </div>\n </SelectionToolbar>\n </Show>\n );\n}\n"],"mappings":"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","ignoreList":[]}
@@ -8,10 +8,11 @@ import { createComponent as _$createComponent } from "solid-js/web";
8
8
  import { getNextElement as _$getNextElement } from "solid-js/web";
9
9
  var _tmpl$ = /*#__PURE__*/_$template(`<span class=k2b-field__required aria-hidden=true>*`),
10
10
  _tmpl$2 = /*#__PURE__*/_$template(`<label class=k2b-field__label><!$><!/><!$><!/>`),
11
- _tmpl$3 = /*#__PURE__*/_$template(`<p class=k2b-field__description>`),
12
- _tmpl$4 = /*#__PURE__*/_$template(`<p class=k2b-field__error role=alert aria-live=polite>`),
13
- _tmpl$5 = /*#__PURE__*/_$template(`<div><!$><!/><!$><!/><!$><!/><!$><!/>`),
14
- _tmpl$6 = /*#__PURE__*/_$template(`<span class=k2b-field__label><!$><!/><!$><!/>`);
11
+ _tmpl$3 = /*#__PURE__*/_$template(`<span class=k2b-field__label><!$><!/><!$><!/>`),
12
+ _tmpl$4 = /*#__PURE__*/_$template(`<div class=k2b-field__label-row><!$><!/><!$><!/>`),
13
+ _tmpl$5 = /*#__PURE__*/_$template(`<p class=k2b-field__description>`),
14
+ _tmpl$6 = /*#__PURE__*/_$template(`<p class=k2b-field__error role=alert aria-live=polite>`),
15
+ _tmpl$7 = /*#__PURE__*/_$template(`<div><!$><!/><!$><!/><!$><!/><!$><!/>`);
15
16
  import { createUniqueId, Show } from "solid-js";
16
17
  import { resolveMaybeAccessor } from "../inputs/field-contract";
17
18
  export const createFieldMeta = id => {
@@ -26,107 +27,125 @@ export const createFieldMeta = id => {
26
27
  };
27
28
  export function Field(props) {
28
29
  const error = () => resolveMaybeAccessor(props.error);
30
+ const label = () => _$createComponent(Show, {
31
+ get when() {
32
+ return props.labelFor !== false;
33
+ },
34
+ get fallback() {
35
+ return (() => {
36
+ var _el$7 = _$getNextElement(_tmpl$3),
37
+ _el$9 = _el$7.firstChild,
38
+ [_el$0, _co$3] = _$getNextMarker(_el$9.nextSibling),
39
+ _el$1 = _el$0.nextSibling,
40
+ [_el$10, _co$4] = _$getNextMarker(_el$1.nextSibling);
41
+ _$insert(_el$7, () => props.label, _el$0, _co$3);
42
+ _$insert(_el$7, _$createComponent(Show, {
43
+ get when() {
44
+ return props.required;
45
+ },
46
+ get children() {
47
+ return _$getNextElement(_tmpl$);
48
+ }
49
+ }), _el$10, _co$4);
50
+ _$effect(() => _$setAttribute(_el$7, "id", props.meta.labelId));
51
+ return _el$7;
52
+ })();
53
+ },
54
+ get children() {
55
+ var _el$ = _$getNextElement(_tmpl$2),
56
+ _el$3 = _el$.firstChild,
57
+ [_el$4, _co$] = _$getNextMarker(_el$3.nextSibling),
58
+ _el$5 = _el$4.nextSibling,
59
+ [_el$6, _co$2] = _$getNextMarker(_el$5.nextSibling);
60
+ _$insert(_el$, () => props.label, _el$4, _co$);
61
+ _$insert(_el$, _$createComponent(Show, {
62
+ get when() {
63
+ return props.required;
64
+ },
65
+ get children() {
66
+ return _$getNextElement(_tmpl$);
67
+ }
68
+ }), _el$6, _co$2);
69
+ _$effect(_p$ => {
70
+ var _v$ = props.meta.labelId,
71
+ _v$2 = props.labelFor || props.meta.controlId;
72
+ _v$ !== _p$.e && _$setAttribute(_el$, "id", _p$.e = _v$);
73
+ _v$2 !== _p$.t && _$setAttribute(_el$, "for", _p$.t = _v$2);
74
+ return _p$;
75
+ }, {
76
+ e: undefined,
77
+ t: undefined
78
+ });
79
+ return _el$;
80
+ }
81
+ });
29
82
  return (() => {
30
- var _el$ = _$getNextElement(_tmpl$5),
31
- _el$0 = _el$.firstChild,
32
- [_el$1, _co$3] = _$getNextMarker(_el$0.nextSibling),
33
- _el$10 = _el$1.nextSibling,
34
- [_el$11, _co$4] = _$getNextMarker(_el$10.nextSibling),
35
- _el$12 = _el$11.nextSibling,
36
- [_el$13, _co$5] = _$getNextMarker(_el$12.nextSibling),
37
- _el$14 = _el$13.nextSibling,
38
- [_el$15, _co$6] = _$getNextMarker(_el$14.nextSibling);
39
- _$insert(_el$, _$createComponent(Show, {
83
+ var _el$11 = _$getNextElement(_tmpl$7),
84
+ _el$19 = _el$11.firstChild,
85
+ [_el$20, _co$7] = _$getNextMarker(_el$19.nextSibling),
86
+ _el$21 = _el$20.nextSibling,
87
+ [_el$22, _co$8] = _$getNextMarker(_el$21.nextSibling),
88
+ _el$23 = _el$22.nextSibling,
89
+ [_el$24, _co$9] = _$getNextMarker(_el$23.nextSibling),
90
+ _el$25 = _el$24.nextSibling,
91
+ [_el$26, _co$0] = _$getNextMarker(_el$25.nextSibling);
92
+ _$insert(_el$11, _$createComponent(Show, {
40
93
  get when() {
41
94
  return props.label;
42
95
  },
43
96
  get children() {
44
97
  return _$createComponent(Show, {
45
98
  get when() {
46
- return props.labelFor !== false;
99
+ return props.labelEnd;
47
100
  },
48
101
  get fallback() {
49
- return (() => {
50
- var _el$16 = _$getNextElement(_tmpl$6),
51
- _el$18 = _el$16.firstChild,
52
- [_el$19, _co$7] = _$getNextMarker(_el$18.nextSibling),
53
- _el$20 = _el$19.nextSibling,
54
- [_el$21, _co$8] = _$getNextMarker(_el$20.nextSibling);
55
- _$insert(_el$16, () => props.label, _el$19, _co$7);
56
- _$insert(_el$16, _$createComponent(Show, {
57
- get when() {
58
- return props.required;
59
- },
60
- get children() {
61
- return _$getNextElement(_tmpl$);
62
- }
63
- }), _el$21, _co$8);
64
- _$effect(() => _$setAttribute(_el$16, "id", props.meta.labelId));
65
- return _el$16;
66
- })();
102
+ return label();
67
103
  },
68
104
  get children() {
69
- var _el$2 = _$getNextElement(_tmpl$2),
70
- _el$4 = _el$2.firstChild,
71
- [_el$5, _co$] = _$getNextMarker(_el$4.nextSibling),
72
- _el$6 = _el$5.nextSibling,
73
- [_el$7, _co$2] = _$getNextMarker(_el$6.nextSibling);
74
- _$insert(_el$2, () => props.label, _el$5, _co$);
75
- _$insert(_el$2, _$createComponent(Show, {
76
- get when() {
77
- return props.required;
78
- },
79
- get children() {
80
- return _$getNextElement(_tmpl$);
81
- }
82
- }), _el$7, _co$2);
83
- _$effect(_p$ => {
84
- var _v$ = props.meta.labelId,
85
- _v$2 = props.labelFor || props.meta.controlId;
86
- _v$ !== _p$.e && _$setAttribute(_el$2, "id", _p$.e = _v$);
87
- _v$2 !== _p$.t && _$setAttribute(_el$2, "for", _p$.t = _v$2);
88
- return _p$;
89
- }, {
90
- e: undefined,
91
- t: undefined
92
- });
93
- return _el$2;
105
+ var _el$12 = _$getNextElement(_tmpl$4),
106
+ _el$13 = _el$12.firstChild,
107
+ [_el$14, _co$5] = _$getNextMarker(_el$13.nextSibling),
108
+ _el$15 = _el$14.nextSibling,
109
+ [_el$16, _co$6] = _$getNextMarker(_el$15.nextSibling);
110
+ _$insert(_el$12, label, _el$14, _co$5);
111
+ _$insert(_el$12, () => props.labelEnd, _el$16, _co$6);
112
+ return _el$12;
94
113
  }
95
114
  });
96
115
  }
97
- }), _el$1, _co$3);
98
- _$insert(_el$, _$createComponent(Show, {
116
+ }), _el$20, _co$7);
117
+ _$insert(_el$11, _$createComponent(Show, {
99
118
  get when() {
100
119
  return props.description;
101
120
  },
102
121
  get children() {
103
- var _el$8 = _$getNextElement(_tmpl$3);
104
- _$insert(_el$8, () => props.description);
105
- _$effect(() => _$setAttribute(_el$8, "id", props.meta.descriptionId));
106
- return _el$8;
122
+ var _el$17 = _$getNextElement(_tmpl$5);
123
+ _$insert(_el$17, () => props.description);
124
+ _$effect(() => _$setAttribute(_el$17, "id", props.meta.descriptionId));
125
+ return _el$17;
107
126
  }
108
- }), _el$11, _co$4);
109
- _$insert(_el$, () => props.children, _el$13, _co$5);
110
- _$insert(_el$, _$createComponent(Show, {
127
+ }), _el$22, _co$8);
128
+ _$insert(_el$11, () => props.children, _el$24, _co$9);
129
+ _$insert(_el$11, _$createComponent(Show, {
111
130
  get when() {
112
131
  return error();
113
132
  },
114
133
  get children() {
115
- var _el$9 = _$getNextElement(_tmpl$4);
116
- _$insert(_el$9, error);
117
- _$effect(() => _$setAttribute(_el$9, "id", props.meta.errorId));
118
- return _el$9;
134
+ var _el$18 = _$getNextElement(_tmpl$6);
135
+ _$insert(_el$18, error);
136
+ _$effect(() => _$setAttribute(_el$18, "id", props.meta.errorId));
137
+ return _el$18;
119
138
  }
120
- }), _el$15, _co$6);
139
+ }), _el$26, _co$0);
121
140
  _$effect(_p$ => {
122
141
  var _v$3 = `k2b-field ${props.class ?? ""}`,
123
142
  _v$4 = props.disabled ? "true" : undefined,
124
143
  _v$5 = props.fill ? "true" : undefined,
125
144
  _v$6 = error() ? "true" : undefined;
126
- _v$3 !== _p$.e && _$className(_el$, _p$.e = _v$3);
127
- _v$4 !== _p$.t && _$setAttribute(_el$, "data-disabled", _p$.t = _v$4);
128
- _v$5 !== _p$.a && _$setAttribute(_el$, "data-fill", _p$.a = _v$5);
129
- _v$6 !== _p$.o && _$setAttribute(_el$, "data-invalid", _p$.o = _v$6);
145
+ _v$3 !== _p$.e && _$className(_el$11, _p$.e = _v$3);
146
+ _v$4 !== _p$.t && _$setAttribute(_el$11, "data-disabled", _p$.t = _v$4);
147
+ _v$5 !== _p$.a && _$setAttribute(_el$11, "data-fill", _p$.a = _v$5);
148
+ _v$6 !== _p$.o && _$setAttribute(_el$11, "data-invalid", _p$.o = _v$6);
130
149
  return _p$;
131
150
  }, {
132
151
  e: undefined,
@@ -134,7 +153,7 @@ export function Field(props) {
134
153
  a: undefined,
135
154
  o: undefined
136
155
  });
137
- return _el$;
156
+ return _el$11;
138
157
  })();
139
158
  }
140
159
  export const fieldDescribedBy = (meta, owner) => [owner["aria-describedby"], owner.description ? meta.descriptionId : undefined, resolveMaybeAccessor(owner.error) ? meta.errorId : undefined].filter(Boolean).join(" ") || undefined;
@@ -1 +1 @@
1
- {"version":3,"names":["aria-label","aria-labelledby","aria-describedby","aria-invalid","aria-required"],"sources":["internal/field.tsx"],"sourcesContent":["import { createUniqueId, type JSX, Show } from \"solid-js\";\nimport type { FieldProps } from \"../inputs/field-contract\";\nimport { resolveMaybeAccessor } from \"../inputs/field-contract\";\n\nexport type FieldMeta = {\n controlId: string;\n labelId: string;\n descriptionId: string;\n errorId: string;\n};\n\nexport const createFieldMeta = (id?: string): FieldMeta => {\n const generatedId = createUniqueId();\n const controlId = id ?? `k2b-field-${generatedId}`;\n\n return {\n controlId,\n labelId: `${controlId}-label`,\n descriptionId: `${controlId}-description`,\n errorId: `${controlId}-error`,\n };\n};\n\ntype FieldLayoutProps = {\n children: JSX.Element;\n meta: FieldMeta;\n fill?: boolean;\n /** Composite controls use aria-labelledby instead of an HTML label target. */\n labelFor?: string | false;\n} & Pick<FieldProps, \"class\" | \"description\" | \"error\" | \"label\" | \"required\" | \"disabled\">;\n\nexport function Field(props: FieldLayoutProps): JSX.Element {\n const error = () => resolveMaybeAccessor(props.error);\n\n return (\n <div\n class={`k2b-field ${props.class ?? \"\"}`}\n data-disabled={props.disabled ? \"true\" : undefined}\n data-fill={props.fill ? \"true\" : undefined}\n data-invalid={error() ? \"true\" : undefined}\n >\n <Show when={props.label}>\n <Show\n when={props.labelFor !== false}\n fallback={\n <span id={props.meta.labelId} class=\"k2b-field__label\">\n {props.label}\n <Show when={props.required}>\n <span class=\"k2b-field__required\" aria-hidden=\"true\">\n *\n </span>\n </Show>\n </span>\n }\n >\n <label id={props.meta.labelId} class=\"k2b-field__label\" for={props.labelFor || props.meta.controlId}>\n {props.label}\n <Show when={props.required}>\n <span class=\"k2b-field__required\" aria-hidden=\"true\">\n *\n </span>\n </Show>\n </label>\n </Show>\n </Show>\n <Show when={props.description}>\n <p class=\"k2b-field__description\" id={props.meta.descriptionId}>\n {props.description}\n </p>\n </Show>\n {props.children}\n <Show when={error()}>\n <p class=\"k2b-field__error\" id={props.meta.errorId} role=\"alert\" aria-live=\"polite\">\n {error()}\n </p>\n </Show>\n </div>\n );\n}\n\ntype FieldAriaOwner = Pick<FieldProps, \"aria-describedby\" | \"aria-label\" | \"description\" | \"error\" | \"label\" | \"required\">;\n\nexport const fieldDescribedBy = (meta: FieldMeta, owner: FieldAriaOwner): string | undefined =>\n [\n owner[\"aria-describedby\"],\n owner.description ? meta.descriptionId : undefined,\n resolveMaybeAccessor(owner.error) ? meta.errorId : undefined,\n ]\n .filter(Boolean)\n .join(\" \") || undefined;\n\nexport const fieldControlAria = (meta: FieldMeta, owner: FieldAriaOwner) => ({\n get \"aria-label\"() {\n return owner.label ? undefined : owner[\"aria-label\"];\n },\n get \"aria-labelledby\"() {\n return owner.label ? meta.labelId : undefined;\n },\n get \"aria-describedby\"() {\n return fieldDescribedBy(meta, owner);\n },\n get \"aria-invalid\"() {\n return resolveMaybeAccessor(owner.error) ? (\"true\" as const) : undefined;\n },\n get \"aria-required\"() {\n return owner.required || undefined;\n },\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["aria-label","aria-labelledby","aria-describedby","aria-invalid","aria-required"],"sources":["internal/field.tsx"],"sourcesContent":["import { createUniqueId, type JSX, Show } from \"solid-js\";\nimport type { FieldProps } from \"../inputs/field-contract\";\nimport { resolveMaybeAccessor } from \"../inputs/field-contract\";\n\nexport type FieldMeta = {\n controlId: string;\n labelId: string;\n descriptionId: string;\n errorId: string;\n};\n\nexport const createFieldMeta = (id?: string): FieldMeta => {\n const generatedId = createUniqueId();\n const controlId = id ?? `k2b-field-${generatedId}`;\n\n return {\n controlId,\n labelId: `${controlId}-label`,\n descriptionId: `${controlId}-description`,\n errorId: `${controlId}-error`,\n };\n};\n\ntype FieldLayoutProps = {\n children: JSX.Element;\n meta: FieldMeta;\n fill?: boolean;\n /** Composite controls use aria-labelledby instead of an HTML label target. */\n labelFor?: string | false;\n /** Optional controls beside the label, outside its clickable target. */\n labelEnd?: JSX.Element;\n} & Pick<FieldProps, \"class\" | \"description\" | \"error\" | \"label\" | \"required\" | \"disabled\">;\n\nexport function Field(props: FieldLayoutProps): JSX.Element {\n const error = () => resolveMaybeAccessor(props.error);\n const label = () => (\n <Show\n when={props.labelFor !== false}\n fallback={\n <span id={props.meta.labelId} class=\"k2b-field__label\">\n {props.label}\n <Show when={props.required}>\n <span class=\"k2b-field__required\" aria-hidden=\"true\">\n *\n </span>\n </Show>\n </span>\n }\n >\n <label id={props.meta.labelId} class=\"k2b-field__label\" for={props.labelFor || props.meta.controlId}>\n {props.label}\n <Show when={props.required}>\n <span class=\"k2b-field__required\" aria-hidden=\"true\">\n *\n </span>\n </Show>\n </label>\n </Show>\n );\n\n return (\n <div\n class={`k2b-field ${props.class ?? \"\"}`}\n data-disabled={props.disabled ? \"true\" : undefined}\n data-fill={props.fill ? \"true\" : undefined}\n data-invalid={error() ? \"true\" : undefined}\n >\n <Show when={props.label}>\n <Show when={props.labelEnd} fallback={label()}>\n <div class=\"k2b-field__label-row\">\n {label()}\n {props.labelEnd}\n </div>\n </Show>\n </Show>\n <Show when={props.description}>\n <p class=\"k2b-field__description\" id={props.meta.descriptionId}>\n {props.description}\n </p>\n </Show>\n {props.children}\n <Show when={error()}>\n <p class=\"k2b-field__error\" id={props.meta.errorId} role=\"alert\" aria-live=\"polite\">\n {error()}\n </p>\n </Show>\n </div>\n );\n}\n\ntype FieldAriaOwner = Pick<FieldProps, \"aria-describedby\" | \"aria-label\" | \"description\" | \"error\" | \"label\" | \"required\">;\n\nexport const fieldDescribedBy = (meta: FieldMeta, owner: FieldAriaOwner): string | undefined =>\n [\n owner[\"aria-describedby\"],\n owner.description ? meta.descriptionId : undefined,\n resolveMaybeAccessor(owner.error) ? meta.errorId : undefined,\n ]\n .filter(Boolean)\n .join(\" \") || undefined;\n\nexport const fieldControlAria = (meta: FieldMeta, owner: FieldAriaOwner) => ({\n get \"aria-label\"() {\n return owner.label ? undefined : owner[\"aria-label\"];\n },\n get \"aria-labelledby\"() {\n return owner.label ? meta.labelId : undefined;\n },\n get \"aria-describedby\"() {\n return fieldDescribedBy(meta, owner);\n },\n get \"aria-invalid\"() {\n return resolveMaybeAccessor(owner.error) ? (\"true\" as const) : undefined;\n },\n get \"aria-required\"() {\n return owner.required || undefined;\n },\n});\n"],"mappings":"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","ignoreList":[]}