@adecore/ui 0.31.11 → 0.32.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 (163) hide show
  1. package/dist/AccentSwatches.js +290 -13
  2. package/dist/Banner.js +90 -9
  3. package/dist/Button.js +114 -22
  4. package/dist/ButtonGroup.js +62 -8
  5. package/dist/Checkbox.js +73 -4
  6. package/dist/ChoiceCards.js +205 -11
  7. package/dist/CloseButton.js +87 -7
  8. package/dist/ColorSwatch.js +132 -15
  9. package/dist/ColorWheelPicker.js +305 -71
  10. package/dist/ColumnResizeHandle.js +43 -8
  11. package/dist/DisabledReason.js +27 -8
  12. package/dist/DockShell.js +144 -37
  13. package/dist/EmptyState.js +95 -6
  14. package/dist/ErrorBoundary.js +254 -31
  15. package/dist/Field.js +349 -31
  16. package/dist/FileIcon.js +67 -6
  17. package/dist/Icon.js +38 -6
  18. package/dist/IconButton.js +176 -20
  19. package/dist/IconPicker.js +344 -73
  20. package/dist/Input.js +233 -14
  21. package/dist/Kbd.js +150 -10
  22. package/dist/LazyBoundary.js +14 -5
  23. package/dist/ListRow.js +75 -15
  24. package/dist/Meter.js +108 -5
  25. package/dist/MiddleTruncate.js +126 -45
  26. package/dist/PanelEmpty.js +64 -5
  27. package/dist/PanelHeader.js +95 -13
  28. package/dist/Pill.js +114 -19
  29. package/dist/ProjectSwitcher.js +225 -12
  30. package/dist/PromptDialog.js +352 -37
  31. package/dist/SectionLabel.js +62 -8
  32. package/dist/SegmentBar.js +197 -36
  33. package/dist/Segmented.js +130 -23
  34. package/dist/Select.js +310 -19
  35. package/dist/SelectSearch.js +344 -29
  36. package/dist/Separator.js +35 -4
  37. package/dist/ShortcutHints.js +146 -76
  38. package/dist/Skeleton.js +31 -4
  39. package/dist/Slider.js +172 -10
  40. package/dist/SlidingColumn.js +194 -34
  41. package/dist/Spinner.js +100 -3
  42. package/dist/Stepper.js +232 -11
  43. package/dist/Surface.js +62 -8
  44. package/dist/Switch.js +60 -6
  45. package/dist/TextMenu.js +212 -17
  46. package/dist/Tile.js +149 -5
  47. package/dist/Toasts.js +391 -33
  48. package/dist/Tooltip.js +153 -16
  49. package/dist/UIProvider.js +62 -15
  50. package/dist/Waveform.js +362 -93
  51. package/dist/Wipe.js +259 -34
  52. package/dist/ZoomControls.js +356 -14
  53. package/dist/class-name.js +1 -1
  54. package/dist/clipboard.js +15 -17
  55. package/dist/context-menu/index.parts.js +1 -1
  56. package/dist/dialog/index.parts.js +1 -1
  57. package/dist/dialog/parts.js +378 -29
  58. package/dist/dialog-layer.js +51 -18
  59. package/dist/error-boundary.js +19 -19
  60. package/dist/error-message.js +1 -1
  61. package/dist/field-context.js +7 -5
  62. package/dist/file-icon.js +23 -21
  63. package/dist/file-tree/helpers.js +133 -119
  64. package/dist/file-tree/index.parts.js +3 -3
  65. package/dist/file-tree/parts.js +418 -127
  66. package/dist/file-tree/style.js +1 -1
  67. package/dist/file-tree/use-file-tree-shift.js +43 -30
  68. package/dist/file-tree/use-file-tree.js +60 -18
  69. package/dist/file-tree/use-slots.js +220 -192
  70. package/dist/floating.js +2 -2
  71. package/dist/format/datetime.js +88 -38
  72. package/dist/format/duration.js +59 -53
  73. package/dist/format/index.js +1 -1
  74. package/dist/format/locale.js +76 -56
  75. package/dist/format/number.js +77 -61
  76. package/dist/format/regions.js +4 -2
  77. package/dist/format/time-zone.js +1 -1
  78. package/dist/icon-button-size.js +12 -2
  79. package/dist/icon-picker.js +70 -61
  80. package/dist/index.js +57 -57
  81. package/dist/key-value-list/index.parts.js +1 -1
  82. package/dist/key-value-list/parts.js +256 -22
  83. package/dist/lazy-landings.js +10 -10
  84. package/dist/lazy.js +84 -71
  85. package/dist/locales/en.js +80 -80
  86. package/dist/locales/nl.js +80 -80
  87. package/dist/locales.js +10 -7
  88. package/dist/menu/index.parts.js +1 -1
  89. package/dist/menu/parts.js +882 -44
  90. package/dist/merge-refs.js +8 -9
  91. package/dist/middle-truncate.js +24 -25
  92. package/dist/modality.js +27 -19
  93. package/dist/placement.js +11 -20
  94. package/dist/platform.js +6 -6
  95. package/dist/popover/index.parts.js +1 -1
  96. package/dist/popover/parts.js +173 -11
  97. package/dist/popup-layer.js +38 -17
  98. package/dist/prefetch.js +78 -79
  99. package/dist/preview-card/index.parts.js +1 -1
  100. package/dist/project-switcher-row.js +153 -12
  101. package/dist/select-row.js +69 -5
  102. package/dist/select-shared.js +6 -6
  103. package/dist/selection.js +16 -16
  104. package/dist/seti-icons.js +413 -413
  105. package/dist/settings/ConfirmDialog.js +55 -8
  106. package/dist/settings/DetailHeader.js +72 -4
  107. package/dist/settings/MasterDetail.js +119 -7
  108. package/dist/settings/SettingsDialog.js +820 -80
  109. package/dist/settings/SettingsRow.js +205 -18
  110. package/dist/settings/SettingsSection.js +96 -6
  111. package/dist/settings/index.js +7 -7
  112. package/dist/settings/target.js +7 -2
  113. package/dist/shortcut-hints.js +73 -55
  114. package/dist/shortcut.js +140 -104
  115. package/dist/step-places.js +1 -1
  116. package/dist/tabs/index.parts.js +1 -1
  117. package/dist/tabs/overflow.js +18 -18
  118. package/dist/tabs/parts.js +780 -166
  119. package/dist/testing/dedupe.js +82 -75
  120. package/dist/testing/fake-source.js +12 -12
  121. package/dist/testing/index.js +1 -1
  122. package/dist/toast-store.js +65 -46
  123. package/dist/tree/index.parts.js +1 -1
  124. package/dist/tree/parts.js +721 -94
  125. package/dist/tree/shift.js +28 -22
  126. package/dist/tree/style.js +2 -2
  127. package/dist/tree/use-tree-shift.js +178 -117
  128. package/dist/useAsyncAction.js +23 -19
  129. package/dist/useColumnResize.js +36 -34
  130. package/dist/useContentSize.js +62 -18
  131. package/dist/useMeasuredWidth.js +14 -3
  132. package/dist/useNow.js +73 -30
  133. package/dist/wipe-split.js +14 -14
  134. package/dist/workspace/DropPreview.js +60 -7
  135. package/dist/workspace/SplitView.js +1025 -441
  136. package/dist/workspace/TabStrip.js +810 -191
  137. package/dist/workspace/Workspace.js +276 -26
  138. package/dist/workspace/context.js +8 -3
  139. package/dist/workspace/geometry.js +173 -150
  140. package/dist/workspace/model.js +313 -250
  141. package/dist/workspace/preview.js +61 -61
  142. package/dist/zoom.js +2 -2
  143. package/package.json +1 -1
  144. package/src/ErrorBoundary.tsx +1 -1
  145. package/src/Field.tsx +4 -3
  146. package/src/IconPicker.tsx +3 -3
  147. package/src/LazyBoundary.tsx +2 -0
  148. package/src/MiddleTruncate.tsx +2 -2
  149. package/src/SegmentBar.tsx +2 -2
  150. package/src/Toasts.tsx +3 -1
  151. package/src/Tooltip.tsx +7 -10
  152. package/src/Waveform.tsx +3 -3
  153. package/src/file-tree/parts.tsx +6 -9
  154. package/src/file-tree/use-file-tree-shift.tsx +6 -9
  155. package/src/lazy.tsx +4 -0
  156. package/src/locales/en.ts +4 -4
  157. package/src/locales/nl.ts +5 -5
  158. package/src/settings/SettingsDialog.tsx +1 -1
  159. package/src/tree/parts.tsx +5 -8
  160. package/src/useContentSize.ts +3 -3
  161. package/src/workspace/SplitView.tsx +2 -2
  162. package/src/workspace/TabStrip.tsx +2 -3
  163. package/src/workspace/Workspace.tsx +2 -5
@@ -1,30 +1,217 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { c as _c } from "react/compiler-runtime";
2
2
  import { useEffect, useRef } from 'react';
3
3
  import clsx from 'clsx';
4
- import { Icon } from '../Icon.js';
4
+ import { Icon } from "../Icon.js";
5
5
  import { mergeRefs } from '../merge-refs.js';
6
6
  import { useSettingsTarget } from './target.js';
7
7
  /* How long a row a search result jumped to stays lit. */
8
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
9
  const TARGET_MS = 1600;
9
10
  /* An icon beside text that may wrap: the box is one line of `text-sm` high, so the icon sits on the first line. */
10
- export function TopIcon({ icon, size = 16, className, ref }) {
11
- return (_jsx("span", { ref: ref, className: "flex h-5.5 shrink-0 items-center", children: _jsx(Icon, { icon: icon, size: size, className: className }) }));
11
+ export function TopIcon(t0) {
12
+ const $ = _c(7);
13
+ const {
14
+ icon,
15
+ size: t1,
16
+ className,
17
+ ref
18
+ } = t0;
19
+ const size = t1 === undefined ? 16 : t1;
20
+ let t2;
21
+ if ($[0] !== className || $[1] !== icon || $[2] !== size) {
22
+ t2 = /*#__PURE__*/_jsx(Icon, {
23
+ icon: icon,
24
+ size: size,
25
+ className: className
26
+ });
27
+ $[0] = className;
28
+ $[1] = icon;
29
+ $[2] = size;
30
+ $[3] = t2;
31
+ } else {
32
+ t2 = $[3];
33
+ }
34
+ let t3;
35
+ if ($[4] !== ref || $[5] !== t2) {
36
+ t3 = /*#__PURE__*/_jsx("span", {
37
+ ref: ref,
38
+ className: "flex h-5.5 shrink-0 items-center",
39
+ children: t2
40
+ });
41
+ $[4] = ref;
42
+ $[5] = t2;
43
+ $[6] = t3;
44
+ } else {
45
+ t3 = $[6];
46
+ }
47
+ return t3;
12
48
  }
13
49
  /*
14
50
  * One setting: what it is on the left, the control on the right. Where the two do not fit side by
15
51
  * side (a tablet, a narrow window) the control wraps under the label instead of widening the dialog.
16
52
  */
17
- export function SettingsRow({ label, description, control, children, muted = false, leading, indent = false, searchId, className, ref }) {
18
- const row = useRef(null);
19
- const { target, shown } = useSettingsTarget();
20
- const targeted = searchId !== undefined && target === searchId;
21
- useEffect(() => {
22
- if (!targeted) {
23
- return;
24
- }
25
- row.current?.scrollIntoView({ block: 'center' });
26
- const timer = window.setTimeout(shown, TARGET_MS);
27
- return () => window.clearTimeout(timer);
28
- }, [targeted, shown]);
29
- return (_jsxs("div", { ref: mergeRefs(row, ref), "data-settings-row": searchId, className: clsx('flex min-w-0 flex-col gap-3 pr-4.5 transition-colors duration-500 first:rounded-t-xl last:rounded-b-xl', indent ? 'pl-14.5' : 'pl-4.5', description || children || leading ? 'py-3.5' : 'py-3', targeted && 'bg-accent-soft duration-0', className), children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-x-5 gap-y-2", children: [_jsxs("div", { className: "flex min-w-0 grow basis-60 items-start gap-3", children: [leading, _jsxs("div", { className: "min-w-0 grow", children: [_jsx("div", { className: clsx('text-sm break-words', muted ? 'text-text-muted' : 'text-text'), children: label }), description && _jsx("div", { className: "mt-0.5 text-xs break-words text-text-muted", children: description })] })] }), control && _jsx("div", { className: "ml-auto flex max-w-full min-w-0 flex-wrap items-center justify-end gap-2", children: control })] }), children] }));
30
- }
53
+ export function SettingsRow(t0) {
54
+ const $ = _c(35);
55
+ const {
56
+ label,
57
+ description,
58
+ control,
59
+ children,
60
+ muted: t1,
61
+ leading,
62
+ indent: t2,
63
+ searchId,
64
+ className,
65
+ ref
66
+ } = t0;
67
+ const muted = t1 === undefined ? false : t1;
68
+ const indent = t2 === undefined ? false : t2;
69
+ const row = useRef(null);
70
+ const {
71
+ target,
72
+ shown
73
+ } = useSettingsTarget();
74
+ const targeted = searchId !== undefined && target === searchId;
75
+ let t3;
76
+ let t4;
77
+ if ($[0] !== shown || $[1] !== targeted) {
78
+ t3 = () => {
79
+ if (!targeted) {
80
+ return;
81
+ }
82
+ row.current?.scrollIntoView({
83
+ block: "center"
84
+ });
85
+ const timer = window.setTimeout(shown, TARGET_MS);
86
+ return () => window.clearTimeout(timer);
87
+ };
88
+ t4 = [targeted, shown];
89
+ $[0] = shown;
90
+ $[1] = targeted;
91
+ $[2] = t3;
92
+ $[3] = t4;
93
+ } else {
94
+ t3 = $[2];
95
+ t4 = $[3];
96
+ }
97
+ useEffect(t3, t4);
98
+ let t5;
99
+ if ($[4] !== ref) {
100
+ t5 = mergeRefs(row, ref);
101
+ $[4] = ref;
102
+ $[5] = t5;
103
+ } else {
104
+ t5 = $[5];
105
+ }
106
+ const t6 = indent ? "pl-14.5" : "pl-4.5";
107
+ const t7 = description || children || leading ? "py-3.5" : "py-3";
108
+ const t8 = targeted && "bg-accent-soft duration-0";
109
+ let t9;
110
+ if ($[6] !== className || $[7] !== t6 || $[8] !== t7 || $[9] !== t8) {
111
+ t9 = clsx("flex min-w-0 flex-col gap-3 pr-4.5 transition-colors duration-500 first:rounded-t-xl last:rounded-b-xl", t6, t7, t8, className);
112
+ $[6] = className;
113
+ $[7] = t6;
114
+ $[8] = t7;
115
+ $[9] = t8;
116
+ $[10] = t9;
117
+ } else {
118
+ t9 = $[10];
119
+ }
120
+ const t10 = muted ? "text-text-muted" : "text-text";
121
+ let t11;
122
+ if ($[11] !== t10) {
123
+ t11 = clsx("text-sm break-words", t10);
124
+ $[11] = t10;
125
+ $[12] = t11;
126
+ } else {
127
+ t11 = $[12];
128
+ }
129
+ let t12;
130
+ if ($[13] !== label || $[14] !== t11) {
131
+ t12 = /*#__PURE__*/_jsx("div", {
132
+ className: t11,
133
+ children: label
134
+ });
135
+ $[13] = label;
136
+ $[14] = t11;
137
+ $[15] = t12;
138
+ } else {
139
+ t12 = $[15];
140
+ }
141
+ let t13;
142
+ if ($[16] !== description) {
143
+ t13 = description && /*#__PURE__*/_jsx("div", {
144
+ className: "mt-0.5 text-xs break-words text-text-muted",
145
+ children: description
146
+ });
147
+ $[16] = description;
148
+ $[17] = t13;
149
+ } else {
150
+ t13 = $[17];
151
+ }
152
+ let t14;
153
+ if ($[18] !== t12 || $[19] !== t13) {
154
+ t14 = /*#__PURE__*/_jsxs("div", {
155
+ className: "min-w-0 grow",
156
+ children: [t12, t13]
157
+ });
158
+ $[18] = t12;
159
+ $[19] = t13;
160
+ $[20] = t14;
161
+ } else {
162
+ t14 = $[20];
163
+ }
164
+ let t15;
165
+ if ($[21] !== leading || $[22] !== t14) {
166
+ t15 = /*#__PURE__*/_jsxs("div", {
167
+ className: "flex min-w-0 grow basis-60 items-start gap-3",
168
+ children: [leading, t14]
169
+ });
170
+ $[21] = leading;
171
+ $[22] = t14;
172
+ $[23] = t15;
173
+ } else {
174
+ t15 = $[23];
175
+ }
176
+ let t16;
177
+ if ($[24] !== control) {
178
+ t16 = control && /*#__PURE__*/_jsx("div", {
179
+ className: "ml-auto flex max-w-full min-w-0 flex-wrap items-center justify-end gap-2",
180
+ children: control
181
+ });
182
+ $[24] = control;
183
+ $[25] = t16;
184
+ } else {
185
+ t16 = $[25];
186
+ }
187
+ let t17;
188
+ if ($[26] !== t15 || $[27] !== t16) {
189
+ t17 = /*#__PURE__*/_jsxs("div", {
190
+ className: "flex min-w-0 flex-wrap items-center gap-x-5 gap-y-2",
191
+ children: [t15, t16]
192
+ });
193
+ $[26] = t15;
194
+ $[27] = t16;
195
+ $[28] = t17;
196
+ } else {
197
+ t17 = $[28];
198
+ }
199
+ let t18;
200
+ if ($[29] !== children || $[30] !== searchId || $[31] !== t17 || $[32] !== t5 || $[33] !== t9) {
201
+ t18 = /*#__PURE__*/_jsxs("div", {
202
+ ref: t5,
203
+ "data-settings-row": searchId,
204
+ className: t9,
205
+ children: [t17, children]
206
+ });
207
+ $[29] = children;
208
+ $[30] = searchId;
209
+ $[31] = t17;
210
+ $[32] = t5;
211
+ $[33] = t9;
212
+ $[34] = t18;
213
+ } else {
214
+ t18 = $[34];
215
+ }
216
+ return t18;
217
+ }
@@ -1,8 +1,98 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { c as _c } from "react/compiler-runtime";
2
2
  import clsx from 'clsx';
3
- import { Icon } from '../Icon.js';
3
+ import { Icon } from "../Icon.js";
4
4
  /* A titled group of rows in one card; rows divide themselves with a hairline. Without a title it is the card alone. */
5
- export function SettingsSection({ title, description, icon, tag, action, footer, children, className, ref }) {
6
- const hasHeader = title !== undefined || description !== undefined || tag !== undefined || action !== undefined;
7
- return (_jsxs("section", { ref: ref, className: clsx('flex min-w-0 flex-col gap-2.5', className), "aria-label": title, children: [hasHeader && (_jsxs("div", { className: "flex min-w-0 flex-wrap items-end gap-x-3 gap-y-2", children: [_jsxs("div", { className: "min-w-0 grow basis-48", children: [title !== undefined && (_jsxs("h3", { className: "flex items-center gap-2 text-sm font-medium text-text", children: [icon && _jsx(Icon, { icon: icon, size: 14, className: "shrink-0 text-text-faint" }), title] })), description !== undefined && _jsx("p", { className: "mt-0.5 text-xs break-words text-text-muted", children: description })] }), action, tag] })), _jsx("div", { className: "min-w-0 divide-y divide-border rounded-xl border border-border bg-surface bg-clip-padding", children: children }), footer && _jsx("p", { className: "text-xs text-text-faint", children: footer })] }));
8
- }
5
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
+ export function SettingsSection(t0) {
7
+ const $ = _c(20);
8
+ const {
9
+ title,
10
+ description,
11
+ icon,
12
+ tag,
13
+ action,
14
+ footer,
15
+ children,
16
+ className,
17
+ ref
18
+ } = t0;
19
+ const hasHeader = title !== undefined || description !== undefined || tag !== undefined || action !== undefined;
20
+ let t1;
21
+ if ($[0] !== className) {
22
+ t1 = clsx("flex min-w-0 flex-col gap-2.5", className);
23
+ $[0] = className;
24
+ $[1] = t1;
25
+ } else {
26
+ t1 = $[1];
27
+ }
28
+ let t2;
29
+ if ($[2] !== action || $[3] !== description || $[4] !== hasHeader || $[5] !== icon || $[6] !== tag || $[7] !== title) {
30
+ t2 = hasHeader && /*#__PURE__*/_jsxs("div", {
31
+ className: "flex min-w-0 flex-wrap items-end gap-x-3 gap-y-2",
32
+ children: [/*#__PURE__*/_jsxs("div", {
33
+ className: "min-w-0 grow basis-48",
34
+ children: [title !== undefined && /*#__PURE__*/_jsxs("h3", {
35
+ className: "flex items-center gap-2 text-sm font-medium text-text",
36
+ children: [icon && /*#__PURE__*/_jsx(Icon, {
37
+ icon: icon,
38
+ size: 14,
39
+ className: "shrink-0 text-text-faint"
40
+ }), title]
41
+ }), description !== undefined && /*#__PURE__*/_jsx("p", {
42
+ className: "mt-0.5 text-xs break-words text-text-muted",
43
+ children: description
44
+ })]
45
+ }), action, tag]
46
+ });
47
+ $[2] = action;
48
+ $[3] = description;
49
+ $[4] = hasHeader;
50
+ $[5] = icon;
51
+ $[6] = tag;
52
+ $[7] = title;
53
+ $[8] = t2;
54
+ } else {
55
+ t2 = $[8];
56
+ }
57
+ let t3;
58
+ if ($[9] !== children) {
59
+ t3 = /*#__PURE__*/_jsx("div", {
60
+ className: "min-w-0 divide-y divide-border rounded-xl border border-border bg-surface bg-clip-padding",
61
+ children: children
62
+ });
63
+ $[9] = children;
64
+ $[10] = t3;
65
+ } else {
66
+ t3 = $[10];
67
+ }
68
+ let t4;
69
+ if ($[11] !== footer) {
70
+ t4 = footer && /*#__PURE__*/_jsx("p", {
71
+ className: "text-xs text-text-faint",
72
+ children: footer
73
+ });
74
+ $[11] = footer;
75
+ $[12] = t4;
76
+ } else {
77
+ t4 = $[12];
78
+ }
79
+ let t5;
80
+ if ($[13] !== ref || $[14] !== t1 || $[15] !== t2 || $[16] !== t3 || $[17] !== t4 || $[18] !== title) {
81
+ t5 = /*#__PURE__*/_jsxs("section", {
82
+ ref: ref,
83
+ className: t1,
84
+ "aria-label": title,
85
+ children: [t2, t3, t4]
86
+ });
87
+ $[13] = ref;
88
+ $[14] = t1;
89
+ $[15] = t2;
90
+ $[16] = t3;
91
+ $[17] = t4;
92
+ $[18] = title;
93
+ $[19] = t5;
94
+ } else {
95
+ t5 = $[19];
96
+ }
97
+ return t5;
98
+ }
@@ -1,8 +1,8 @@
1
1
  /* The settings dialog and the parts a pane is built from. */
2
- export { ConfirmDialog } from './ConfirmDialog.js';
3
- export { DetailHeader } from './DetailHeader.js';
4
- export { MasterDetail, MasterItem } from './MasterDetail.js';
5
- export { SettingsDialog } from './SettingsDialog.js';
6
- export { SettingsRow, TopIcon } from './SettingsRow.js';
7
- export { SettingsSection } from './SettingsSection.js';
8
- export { useSettingsTarget } from './target.js';
2
+ export { ConfirmDialog } from "./ConfirmDialog.js";
3
+ export { DetailHeader } from "./DetailHeader.js";
4
+ export { MasterDetail, MasterItem } from "./MasterDetail.js";
5
+ export { SettingsDialog } from "./SettingsDialog.js";
6
+ export { SettingsRow, TopIcon } from "./SettingsRow.js";
7
+ export { SettingsSection } from "./SettingsSection.js";
8
+ export { useSettingsTarget } from './target.js';
@@ -1,3 +1,8 @@
1
1
  import { createContext, useContext } from 'react';
2
- export const SettingsTargetContext = createContext({ target: null, shown: () => { } });
3
- export const useSettingsTarget = () => useContext(SettingsTargetContext);
2
+ export const SettingsTargetContext = createContext({
3
+ target: null,
4
+ shown: () => {}
5
+ });
6
+ export const useSettingsTarget = () => {
7
+ return useContext(SettingsTargetContext);
8
+ };
@@ -4,11 +4,14 @@ const targets = new Map();
4
4
  let nextId = 0;
5
5
  /* Called by every `Tooltip` whose `kbd` is a real shortcut; a phrase about a key is no shortcut to print. */
6
6
  export const registerShortcutHint = (element, shortcut) => {
7
- nextId += 1;
8
- targets.set(element, { id: nextId, shortcut });
9
- return () => {
10
- targets.delete(element);
11
- };
7
+ nextId += 1;
8
+ targets.set(element, {
9
+ id: nextId,
10
+ shortcut
11
+ });
12
+ return () => {
13
+ targets.delete(element);
14
+ };
12
15
  };
13
16
  export const shortcutHintTargets = () => targets;
14
17
  /*
@@ -17,49 +20,49 @@ export const shortcutHintTargets = () => targets;
17
20
  * a shortcut pressed in passing never flashes them.
18
21
  */
19
22
  export class ModifierHold {
20
- apple;
21
- onChange;
22
- timer = null;
23
- shown = false;
24
- constructor(apple, onChange) {
25
- this.apple = apple;
26
- this.onChange = onChange;
27
- }
28
- keyDown(event) {
29
- // A repeat is the key still held; only a fresh press starts the wait.
30
- if (event.repeat && event.key === this.modifierKey()) {
31
- return;
32
- }
33
- this.cancel();
34
- if (event.key === this.modifierKey() && !this.otherModifierHeld(event)) {
35
- this.timer = setTimeout(() => {
36
- this.timer = null;
37
- this.shown = true;
38
- this.onChange(true);
39
- }, HINT_DELAY_MS);
40
- }
23
+ apple;
24
+ onChange;
25
+ timer = null;
26
+ shown = false;
27
+ constructor(apple, onChange) {
28
+ this.apple = apple;
29
+ this.onChange = onChange;
30
+ }
31
+ keyDown(event) {
32
+ // A repeat is the key still held; only a fresh press starts the wait.
33
+ if (event.repeat && event.key === this.modifierKey()) {
34
+ return;
41
35
  }
42
- keyUp(event) {
43
- if (event.key === this.modifierKey()) {
44
- this.cancel();
45
- }
36
+ this.cancel();
37
+ if (event.key === this.modifierKey() && !this.otherModifierHeld(event)) {
38
+ this.timer = setTimeout(() => {
39
+ this.timer = null;
40
+ this.shown = true;
41
+ this.onChange(true);
42
+ }, HINT_DELAY_MS);
46
43
  }
47
- cancel() {
48
- if (this.timer !== null) {
49
- clearTimeout(this.timer);
50
- this.timer = null;
51
- }
52
- if (this.shown) {
53
- this.shown = false;
54
- this.onChange(false);
55
- }
44
+ }
45
+ keyUp(event) {
46
+ if (event.key === this.modifierKey()) {
47
+ this.cancel();
56
48
  }
57
- modifierKey() {
58
- return this.apple ? 'Meta' : 'Control';
49
+ }
50
+ cancel() {
51
+ if (this.timer !== null) {
52
+ clearTimeout(this.timer);
53
+ this.timer = null;
59
54
  }
60
- otherModifierHeld(event) {
61
- return event.altKey || event.shiftKey || (this.apple ? event.ctrlKey : event.metaKey);
55
+ if (this.shown) {
56
+ this.shown = false;
57
+ this.onChange(false);
62
58
  }
59
+ }
60
+ modifierKey() {
61
+ return this.apple ? 'Meta' : 'Control';
62
+ }
63
+ otherModifierHeld(event) {
64
+ return event.altKey || event.shiftKey || (this.apple ? event.ctrlKey : event.metaKey);
65
+ }
63
66
  }
64
67
  const HINT_GAP_PX = 2;
65
68
  /* Room a hint needs to be centered under its button; nearer a window edge it lines up with that edge instead. */
@@ -67,15 +70,30 @@ const EDGE_ROOM_PX = 48;
67
70
  const HINT_HEIGHT_PX = 24;
68
71
  /* Under the button, centered, and above it where the window ends first. */
69
72
  export const placeHint = (rect, viewport) => {
70
- const below = rect.bottom + HINT_GAP_PX + HINT_HEIGHT_PX <= viewport.height;
71
- const top = Math.round(below ? rect.bottom + HINT_GAP_PX : rect.top - HINT_GAP_PX);
72
- const translateY = below ? '0' : '-100%';
73
- const center = (rect.left + rect.right) / 2;
74
- if (center < EDGE_ROOM_PX) {
75
- return { left: Math.round(rect.left), top, translateX: '0', translateY };
76
- }
77
- if (center > viewport.width - EDGE_ROOM_PX) {
78
- return { right: Math.round(viewport.width - rect.right), top, translateX: '0', translateY };
79
- }
80
- return { left: Math.round(center), top, translateX: '-50%', translateY };
81
- };
73
+ const below = rect.bottom + HINT_GAP_PX + HINT_HEIGHT_PX <= viewport.height;
74
+ const top = Math.round(below ? rect.bottom + HINT_GAP_PX : rect.top - HINT_GAP_PX);
75
+ const translateY = below ? '0' : '-100%';
76
+ const center = (rect.left + rect.right) / 2;
77
+ if (center < EDGE_ROOM_PX) {
78
+ return {
79
+ left: Math.round(rect.left),
80
+ top,
81
+ translateX: '0',
82
+ translateY
83
+ };
84
+ }
85
+ if (center > viewport.width - EDGE_ROOM_PX) {
86
+ return {
87
+ right: Math.round(viewport.width - rect.right),
88
+ top,
89
+ translateX: '0',
90
+ translateY
91
+ };
92
+ }
93
+ return {
94
+ left: Math.round(center),
95
+ top,
96
+ translateX: '-50%',
97
+ translateY
98
+ };
99
+ };