@rvx/ui 0.1.7 → 0.1.8

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 (101) hide show
  1. package/dist/common/theme-test.js +1 -2
  2. package/dist/common/theme-test.js.map +1 -1
  3. package/dist/common/theme.d.ts +4 -2
  4. package/dist/common/theme.js +2 -1
  5. package/dist/common/theme.js.map +1 -1
  6. package/dist/components/button.d.ts +1 -1
  7. package/dist/components/button.js +2 -2
  8. package/dist/components/button.js.map +1 -1
  9. package/dist/components/checkbox-test.d.ts +3 -0
  10. package/dist/components/checkbox-test.js +30 -0
  11. package/dist/components/checkbox-test.js.map +1 -0
  12. package/dist/components/checkbox.js +5 -8
  13. package/dist/components/checkbox.js.map +1 -1
  14. package/dist/components/collapse.d.ts +2 -1
  15. package/dist/components/collapse.js +2 -2
  16. package/dist/components/collapse.js.map +1 -1
  17. package/dist/components/column.js +2 -2
  18. package/dist/components/column.js.map +1 -1
  19. package/dist/components/control-group.js +1 -2
  20. package/dist/components/control-group.js.map +1 -1
  21. package/dist/components/dialog.js +23 -21
  22. package/dist/components/dialog.js.map +1 -1
  23. package/dist/components/dropdown-input.js.map +1 -1
  24. package/dist/components/dropdown.js +4 -3
  25. package/dist/components/dropdown.js.map +1 -1
  26. package/dist/components/flex-space.js +2 -2
  27. package/dist/components/flex-space.js.map +1 -1
  28. package/dist/components/heading.d.ts +4 -0
  29. package/dist/components/heading.js +6 -2
  30. package/dist/components/heading.js.map +1 -1
  31. package/dist/components/label.js +2 -2
  32. package/dist/components/label.js.map +1 -1
  33. package/dist/components/layer.d.ts +4 -4
  34. package/dist/components/layer.js +7 -13
  35. package/dist/components/layer.js.map +1 -1
  36. package/dist/components/link.js +2 -2
  37. package/dist/components/link.js.map +1 -1
  38. package/dist/components/page.js +1 -2
  39. package/dist/components/page.js.map +1 -1
  40. package/dist/components/popout.d.ts +2 -1
  41. package/dist/components/popout.js +59 -58
  42. package/dist/components/popout.js.map +1 -1
  43. package/dist/components/popover.js +6 -5
  44. package/dist/components/popover.js.map +1 -1
  45. package/dist/components/radio-buttons.js +3 -2
  46. package/dist/components/radio-buttons.js.map +1 -1
  47. package/dist/components/row.js +2 -2
  48. package/dist/components/row.js.map +1 -1
  49. package/dist/components/scroll-view.js +2 -2
  50. package/dist/components/scroll-view.js.map +1 -1
  51. package/dist/components/text-input.js +2 -2
  52. package/dist/components/text-input.js.map +1 -1
  53. package/dist/components/text.js +1 -2
  54. package/dist/components/text.js.map +1 -1
  55. package/dist/components/validation.d.ts +4 -3
  56. package/dist/components/validation.js +6 -7
  57. package/dist/components/validation.js.map +1 -1
  58. package/dist/components/value.js +1 -2
  59. package/dist/components/value.js.map +1 -1
  60. package/dist/index.d.ts +2 -2
  61. package/dist/index.js +2 -2
  62. package/dist/index.js.map +1 -1
  63. package/dist/test.d.ts +1 -0
  64. package/dist/test.js +1 -0
  65. package/dist/test.js.map +1 -1
  66. package/dist/theme.module.css +108 -41
  67. package/dist/theme.module.css.map +1 -1
  68. package/package.json +2 -2
  69. package/src/common/theme-test.tsx +1 -3
  70. package/src/common/theme.tsx +4 -2
  71. package/src/components/button.tsx +3 -4
  72. package/src/components/checkbox-test.tsx +34 -0
  73. package/src/components/checkbox.tsx +5 -7
  74. package/src/components/collapse.tsx +3 -3
  75. package/src/components/column.tsx +2 -3
  76. package/src/components/control-group.tsx +2 -3
  77. package/src/components/dialog.tsx +23 -22
  78. package/src/components/dropdown-input.tsx +0 -1
  79. package/src/components/dropdown.tsx +4 -4
  80. package/src/components/flex-space.tsx +2 -3
  81. package/src/components/heading.tsx +10 -3
  82. package/src/components/label.tsx +3 -2
  83. package/src/components/layer.tsx +13 -19
  84. package/src/components/link.tsx +2 -3
  85. package/src/components/page.tsx +2 -3
  86. package/src/components/popout.tsx +68 -67
  87. package/src/components/popover.tsx +5 -5
  88. package/src/components/radio-buttons.tsx +3 -3
  89. package/src/components/row.tsx +2 -3
  90. package/src/components/scroll-view.tsx +2 -3
  91. package/src/components/text-input.tsx +2 -3
  92. package/src/components/text.tsx +2 -3
  93. package/src/components/validation.tsx +7 -9
  94. package/src/components/value.tsx +2 -3
  95. package/src/index.tsx +2 -2
  96. package/src/test.tsx +1 -0
  97. package/src/theme/base.scss +10 -5
  98. package/src/theme/components/button.scss +58 -31
  99. package/src/theme/components/control-group.scss +6 -1
  100. package/src/theme/components/link.scss +1 -1
  101. package/src/theme/components/text-input.scss +2 -2
@@ -1,4 +1,4 @@
1
- import { Context, ContextKey, DeriveContext, Expression, extract, get, memo, sig, Signal, teardown, uncapture, untrack, watch, wrapContext } from "rvx";
1
+ import { Context, Expression, get, Inject, memo, sig, Signal, teardown, uncapture, untrack, watch } from "rvx";
2
2
 
3
3
  import { Action, handleActionEvent, keyFor } from "../common/events.js";
4
4
 
@@ -13,7 +13,7 @@ interface LayerInstance {
13
13
  autoFocusFallback: Element | undefined;
14
14
  }
15
15
 
16
- export const LAYER = Symbol.for("rvx-ui:layer-handle") as ContextKey<LayerHandle>;
16
+ export const LAYER = new Context<LayerHandle>();
17
17
 
18
18
  const LAYERS = sig<LayerInstance[]>([
19
19
  {
@@ -35,19 +35,16 @@ uncapture(() => watch(LAYERS, layers => {
35
35
  * Render content inside the root layer.
36
36
  */
37
37
  export function RootLayer(props: {
38
- children: (ctx: Context) => unknown;
38
+ children: () => unknown;
39
39
  }): unknown {
40
40
  const layer = LAYERS.value[0];
41
41
  const root = <div
42
42
  style={{ display: "contents" }}
43
43
  inert={layer.inert}
44
44
  >
45
- <DeriveContext>
46
- {ctx => {
47
- ctx.set(LAYER, new Handle(layer));
48
- return props.children(ctx);
49
- }}
50
- </DeriveContext>
45
+ <Inject context={LAYER} value={new Handle(layer)}>
46
+ {props.children}
47
+ </Inject>
51
48
  </div> as HTMLDivElement;
52
49
  layer.roots.push(root);
53
50
  teardown(() => {
@@ -67,7 +64,7 @@ export function RootLayer(props: {
67
64
  * When disposed, focus is moved back to the previously focused element.
68
65
  */
69
66
  export function Layer(props: {
70
- children: (ctx: Context) => unknown;
67
+ children: () => unknown;
71
68
 
72
69
  /**
73
70
  * If true, all layers below this one are marked as inert until the current context is disposed.
@@ -145,12 +142,9 @@ export function Layer(props: {
145
142
  style={{ display: "contents" }}
146
143
  inert={() => layer.inert.value || !enabled()}
147
144
  >
148
- <DeriveContext>
149
- {ctx => {
150
- ctx.set(LAYER, new Handle(layer));
151
- return props.children(ctx);
152
- }}
153
- </DeriveContext>
145
+ <Inject context={LAYER} value={new Handle(layer)}>
146
+ {props.children}
147
+ </Inject>
154
148
  </div> as HTMLElement;
155
149
  layer.roots.push(root);
156
150
  return root;
@@ -213,14 +207,14 @@ export interface LayerHandle {
213
207
  * Reactively check if the layer in the current context (or the root layer if there is none) is inert.
214
208
  */
215
209
  export function isInertLayer(): boolean {
216
- return extract(LAYER)?.inert ?? untrack(() => LAYERS.value[0]).inert.value;
210
+ return LAYER.current?.inert ?? untrack(() => LAYERS.value[0]).inert.value;
217
211
  }
218
212
 
219
213
  /**
220
214
  * Reactively check if the layer in the current context (or the root layer if there is none) is the top layer.
221
215
  */
222
216
  export function isTopLayer(): boolean {
223
- return extract(LAYER)?.top ?? LAYERS.value.length === 1;
217
+ return LAYER.current?.top ?? LAYERS.value.length === 1;
224
218
  }
225
219
 
226
220
  function instanceContains(instance: LayerInstance, node: Node): boolean {
@@ -253,7 +247,7 @@ class Handle implements LayerHandle {
253
247
  useEvent<K extends keyof WindowEventMap>(type: K, listener: (event: WindowEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void;
254
248
  useEvent(type: string, listener: (event: Event) => void, options?: boolean | AddEventListenerOptions): void;
255
249
  useEvent(type: string, listener: (event: Event) => void, options?: boolean | AddEventListenerOptions): void {
256
- const wrapper = wrapContext((event: Event): void => {
250
+ const wrapper = Context.wrap((event: Event): void => {
257
251
  if (this.top) {
258
252
  listener(event);
259
253
  }
@@ -1,6 +1,5 @@
1
- import { ClassValue, Expression, extract, get, map, optionalString, StyleValue } from "rvx";
1
+ import { ClassValue, Expression, get, map, optionalString, StyleValue } from "rvx";
2
2
  import { isPending } from "rvx/async";
3
-
4
3
  import { Action, handleActionEvent, keyFor } from "../common/events.js";
5
4
  import { THEME } from "../common/theme.js";
6
5
  import { separated } from "../common/types.js";
@@ -72,7 +71,7 @@ export function Link(props: {
72
71
 
73
72
  children?: unknown;
74
73
  }): unknown {
75
- const theme = extract(THEME);
74
+ const theme = THEME.current;
76
75
  const disabled = () => isPending() || get(props.disabled);
77
76
 
78
77
  function action(event: Event) {
@@ -1,5 +1,4 @@
1
- import { ClassValue, Expression, extract, StyleValue } from "rvx";
2
-
1
+ import { ClassValue, Expression, StyleValue } from "rvx";
3
2
  import { THEME } from "../common/theme.js";
4
3
  import { Column } from "./column.js";
5
4
 
@@ -11,7 +10,7 @@ export function Page(props: {
11
10
  style?: StyleValue;
12
11
  children?: unknown;
13
12
  }): unknown {
14
- const theme = extract(THEME);
13
+ const theme = THEME.current;
15
14
  return <div
16
15
  role={props.role}
17
16
  id={props.id}
@@ -1,5 +1,5 @@
1
- import { captureSelf, Emitter, Event as RvxEvent, Expression, extract, get, getContext, ReadonlyContext, render, runInContext, sig, teardown, TeardownHook, untrack, View, viewNodes } from "rvx";
2
-
1
+ import { captureSelf, Context, Expression, get, render, sig, teardown, TeardownHook, untrack, View, viewNodes } from "rvx";
2
+ import { Emitter, Event as RvxEvent } from "rvx/event";
3
3
  import { PASSIVE_ACTION_EVENT } from "../common/events.js";
4
4
  import { axisEquals, Direction, DOWN, flip, getBlockStart, getInlineStart, getSize, getWindowSize, getWindowSpaceAround, INSET, LEFT, RIGHT, ScriptDirection, UP, WritingMode } from "../common/writing-mode.js";
5
5
  import { LAYER, Layer } from "./layer.js";
@@ -132,7 +132,6 @@ interface Instance {
132
132
  * Utility to create automatically placed floating content like popovers or dropdowns.
133
133
  */
134
134
  export class Popout {
135
- #context: ReadonlyContext | undefined;
136
135
  #placement: Expression<PopoutPlacement>;
137
136
  #alignment: Expression<PopoutAlignment>;
138
137
  #content: PopoutContent;
@@ -149,7 +148,6 @@ export class Popout {
149
148
  * The popout hides automatically when the current context is disposed.
150
149
  */
151
150
  constructor(options: PopoutOptions) {
152
- this.#context = getContext();
153
151
  this.#placement = options.placement;
154
152
  this.#alignment = options.alignment;
155
153
  this.#content = options.content;
@@ -167,6 +165,71 @@ export class Popout {
167
165
  return this.#visible.value;
168
166
  }
169
167
 
168
+ #createInstance = Context.wrap((writingMode: WritingMode, scriptDir: ScriptDirection): Instance => {
169
+ return captureSelf(dispose => {
170
+ const instance: Instance = this.#instance = {
171
+ dispose,
172
+ content: undefined!,
173
+ view: undefined!,
174
+ observer: undefined!,
175
+ sizeReference: undefined,
176
+ };
177
+
178
+ instance.view = render(<Layer>
179
+ {() => {
180
+ const layer = LAYER.current!;
181
+ const onForeignEvent = (event: Event): void => {
182
+ if (event.target instanceof Node) {
183
+ if (layer.stackContains(event.target)) {
184
+ return;
185
+ }
186
+ const args = this.#instanceArgs;
187
+ if (args !== undefined) {
188
+ for (const node of viewNodes(args.anchor)) {
189
+ if (node === event.target || node.contains(event.target)) {
190
+ return;
191
+ }
192
+ }
193
+ }
194
+ }
195
+ this.hide();
196
+ };
197
+
198
+ this.#foreignEvents.forEach(t => window.addEventListener(t, onForeignEvent, { passive: true, capture: true }));
199
+ teardown(() => {
200
+ this.#foreignEvents.forEach(t => window.removeEventListener(t, onForeignEvent, { capture: true }));
201
+ });
202
+
203
+ instance!.content = <div style={{
204
+ "position": "fixed",
205
+ "writing-mode": writingMode,
206
+ }} dir={scriptDir}>
207
+ {this.#content({
208
+ popout: this,
209
+ onPlacement: this.#onPlacement.event,
210
+ placement: () => this.#placementState.value,
211
+ setSizeReference: target => {
212
+ instance!.sizeReference = target;
213
+ },
214
+ })}
215
+ </div> as HTMLElement;
216
+ return instance!.content;
217
+ }}
218
+ </Layer>);
219
+ document.body.appendChild(instance.view.take());
220
+
221
+ instance.observer = new ResizeObserver(entries => {
222
+ const args = this.#instanceArgs;
223
+ const size = entries[entries.length - 1]?.borderBoxSize[0];
224
+ if (args !== undefined && size !== undefined && (size.blockSize !== args.contentBlockSize || size.inlineSize !== args.contentInlineSize)) {
225
+ this.show(args.anchor, args.pointerEvent);
226
+ }
227
+ });
228
+ instance.observer.observe(instance.content, { box: "border-box" });
229
+ return instance;
230
+ });
231
+ });
232
+
170
233
  /**
171
234
  * Show the popout or recalculate placement if already visible.
172
235
  *
@@ -223,69 +286,7 @@ export class Popout {
223
286
  // Ensure that there is a popout content instance:
224
287
  let instance = this.#instance;
225
288
  if (instance === undefined) {
226
- runInContext(this.#context, () => {
227
- captureSelf(dispose => {
228
- instance = this.#instance = {
229
- dispose,
230
- content: undefined!,
231
- view: undefined!,
232
- observer: undefined!,
233
- sizeReference: undefined,
234
- };
235
-
236
- instance.view = render(<Layer>
237
- {() => {
238
- const layer = extract(LAYER)!;
239
- const onForeignEvent = (event: Event): void => {
240
- if (event.target instanceof Node) {
241
- if (layer.stackContains(event.target)) {
242
- return;
243
- }
244
- const args = this.#instanceArgs;
245
- if (args !== undefined) {
246
- for (const node of viewNodes(args.anchor)) {
247
- if (node === event.target || node.contains(event.target)) {
248
- return;
249
- }
250
- }
251
- }
252
- }
253
- this.hide();
254
- };
255
-
256
- this.#foreignEvents.forEach(t => window.addEventListener(t, onForeignEvent, { passive: true, capture: true }));
257
- teardown(() => {
258
- this.#foreignEvents.forEach(t => window.removeEventListener(t, onForeignEvent, { capture: true }));
259
- });
260
-
261
- instance!.content = <div style={{
262
- "position": "fixed",
263
- "writing-mode": writingMode,
264
- }} dir={scriptDir}>
265
- {this.#content({
266
- popout: this,
267
- onPlacement: this.#onPlacement.event,
268
- placement: () => this.#placementState.value,
269
- setSizeReference: target => {
270
- instance!.sizeReference = target;
271
- },
272
- })}
273
- </div> as HTMLElement;
274
- return instance!.content;
275
- }}
276
- </Layer>);
277
- document.body.appendChild(instance.view.take());
278
-
279
- instance.observer = new ResizeObserver(entries => {
280
- const args = this.#instanceArgs;
281
- const size = entries[entries.length - 1]?.borderBoxSize[0];
282
- if (args !== undefined && size !== undefined && (size.blockSize !== args.contentBlockSize || size.inlineSize !== args.contentInlineSize)) {
283
- this.show(args.anchor, args.pointerEvent);
284
- }
285
- });
286
- instance.observer.observe(instance.content, { box: "border-box" });
287
- });
288
- });
289
+ instance = this.#createInstance(writingMode!, scriptDir!);
289
290
  }
290
291
 
291
292
  const placementArgs: PopoutPlacementArgs = { gap: 0 };
@@ -1,5 +1,5 @@
1
- import { ClassValue, Expression, extract, get, Inject, map, render, sig, StyleValue, SVG, uniqueId, watch, XMLNS } from "rvx";
2
-
1
+ import { ClassValue, Expression, get, Inject, map, render, sig, StyleValue, SVG, watch, XMLNS } from "rvx";
2
+ import { uniqueId } from "rvx/id";
3
3
  import { Action } from "../common/events.js";
4
4
  import { THEME } from "../common/theme.js";
5
5
  import { DOWN, getSize, getXY, LEFT, RIGHT, UP } from "../common/writing-mode.js";
@@ -76,8 +76,8 @@ export function createPopover(props: {
76
76
  placement: map(props.placement, v => v ?? "block"),
77
77
  alignment: map(props.alignment, v => v ?? "center"),
78
78
  content: ({ popout, onPlacement, placement, setSizeReference }) => {
79
- const theme = extract(THEME);
80
- const layer = extract(LAYER)!;
79
+ const theme = THEME.current;
80
+ const layer = LAYER.current!;
81
81
  const spikeTransform = sig("");
82
82
 
83
83
  layer.useHotkey("escape", () => {
@@ -113,7 +113,7 @@ export function createPopover(props: {
113
113
 
114
114
  const spikeArea = <div class={theme?.popover_spike_area}>
115
115
  <div class={theme?.popover_spike} style={{ transform: spikeTransform }}>
116
- <Inject key={XMLNS} value={SVG}>
116
+ <Inject context={XMLNS} value={SVG}>
117
117
  {() => {
118
118
  return <svg viewBox="0 0 16 16" preserveAspectRatio="none">
119
119
  <path d="M0,16 L8,0 L16,16 Z" />
@@ -1,9 +1,9 @@
1
- import { ClassValue, Expression, extract, For, get, map, optionalString, Signal, string, StyleValue, uniqueId } from "rvx";
1
+ import { ClassValue, Expression, For, get, map, optionalString, Signal, string, StyleValue } from "rvx";
2
2
  import { isPending } from "rvx/async";
3
-
4
3
  import { THEME } from "../common/theme.js";
5
4
  import { Text } from "./text.js";
6
5
  import { validatorFor } from "./validation.js";
6
+ import { uniqueId } from "rvx/id";
7
7
 
8
8
  export interface RadioOption<T> {
9
9
  value: T;
@@ -26,7 +26,7 @@ export function RadioButtons<T>(props: {
26
26
  children?: never;
27
27
  }): unknown {
28
28
  const group = uniqueId();
29
- const theme = extract(THEME);
29
+ const theme = THEME.current;
30
30
 
31
31
  const disabled = props.value instanceof Signal
32
32
  ? () => isPending() || get(props.disabled)
@@ -1,5 +1,4 @@
1
- import { ClassValue, Expression, extract, get, StyleValue } from "rvx";
2
-
1
+ import { ClassValue, Expression, get, StyleValue } from "rvx";
3
2
  import { THEME } from "../common/theme.js";
4
3
  import { SizeContext } from "../common/types.js";
5
4
 
@@ -12,7 +11,7 @@ export function Row(props: {
12
11
  style?: StyleValue;
13
12
  children?: unknown;
14
13
  }): unknown {
15
- const theme = extract(THEME);
14
+ const theme = THEME.current;
16
15
  return <div
17
16
  class={[
18
17
  theme?.row,
@@ -1,5 +1,4 @@
1
- import { ClassValue, extract, sig, StyleValue, teardown } from "rvx";
2
-
1
+ import { ClassValue, sig, StyleValue, teardown } from "rvx";
3
2
  import { debounceEvent } from "../common/events.js";
4
3
  import { THEME } from "../common/theme.js";
5
4
  import { axisEquals, DOWN, getBlockStart, getSize, RIGHT, UP, WritingMode } from "../common/writing-mode.js";
@@ -9,7 +8,7 @@ export function ScrollView(props: {
9
8
  style?: StyleValue;
10
9
  children?: unknown;
11
10
  }): unknown {
12
- const theme = extract(THEME);
11
+ const theme = THEME.current;
13
12
  const vertical = sig<boolean | undefined>(undefined);
14
13
  const scrollbarComp = sig(0);
15
14
  const startIndicator = sig(false);
@@ -1,6 +1,5 @@
1
- import { ClassValue, Expression, extract, get, optionalString, Signal, StyleValue } from "rvx";
1
+ import { ClassValue, Expression, get, optionalString, Signal, StyleValue } from "rvx";
2
2
  import { isPending, waitFor } from "rvx/async";
3
-
4
3
  import { keyFor } from "../common/events.js";
5
4
  import { THEME } from "../common/theme.js";
6
5
  import { validatorFor } from "./validation.js";
@@ -64,7 +63,7 @@ export function TextInput(props: ({
64
63
  "aria-label"?: Expression<string | undefined>;
65
64
  "aria-labelledby"?: Expression<string | undefined>;
66
65
  }): unknown {
67
- const theme = extract(THEME);
66
+ const theme = THEME.current;
68
67
  const disabled = () => isPending() || get(props.disabled);
69
68
 
70
69
  const validator = props.value instanceof Signal ? validatorFor(props.value) : undefined;
@@ -1,5 +1,4 @@
1
- import { ClassValue, Expression, extract, StyleValue } from "rvx";
2
-
1
+ import { ClassValue, Expression, StyleValue } from "rvx";
3
2
  import { THEME } from "../common/theme.js";
4
3
 
5
4
  export function Text(props: {
@@ -8,7 +7,7 @@ export function Text(props: {
8
7
  id?: Expression<string | undefined>;
9
8
  children?: unknown;
10
9
  }): unknown {
11
- const theme = extract(THEME);
10
+ const theme = THEME.current;
12
11
  return <div
13
12
  class={[
14
13
  theme?.text,
@@ -1,16 +1,17 @@
1
- import { ClassValue, ContextKey, Emitter, Event, Expression, extract, For, map, sig, Signal, StyleValue, teardown, trigger, TriggerPipe, uniqueId, untrack } from "rvx";
1
+ import { ClassValue, Context, Expression, For, map, sig, Signal, StyleValue, teardown, trigger, TriggerPipe, untrack } from "rvx";
2
2
  import { TaskSlot } from "rvx/async";
3
-
4
3
  import { THEME } from "../common/theme.js";
5
4
  import { Collapse } from "./collapse.js";
6
5
  import { Text } from "./text.js";
6
+ import { uniqueId } from "rvx/id";
7
+ import { Emitter, Event } from "rvx/event";
7
8
 
8
9
  const VALIDATORS = new WeakMap<object, Validator>();
9
10
 
10
11
  /**
11
- * Context key for validation options used by new validators.
12
+ * Context for validation options used by new validators.
12
13
  */
13
- export const VALIDATION = Symbol.for("rvx-ui:validation") as ContextKey<ValidationOptions>;
14
+ export const VALIDATION = new Context<ValidationOptions>();
14
15
 
15
16
  /**
16
17
  * Defines when accessed signals trigger automatic validation.
@@ -30,10 +31,9 @@ export class Validator {
30
31
  #signalTrigger: ValidationSignalTrigger;
31
32
  #rules = sig<ValidationRuleEntry[]>([]);
32
33
  #invalid = sig(false);
33
- #cycle = 0;
34
34
 
35
35
  constructor() {
36
- const options = extract(VALIDATION);
36
+ const options = VALIDATION.current;
37
37
  this.#signalTrigger = options?.signalTrigger ?? "if-validated";
38
38
  }
39
39
 
@@ -98,7 +98,6 @@ export class Validator {
98
98
  }
99
99
 
100
100
  async #validate(sideEffect: boolean, signal?: AbortSignal): Promise<boolean> {
101
- this.#cycle++;
102
101
  const rules = untrack(() => this.#rules.value);
103
102
  for (let i = 0; i < rules.length; i++) {
104
103
  if (signal?.aborted) {
@@ -143,7 +142,6 @@ export class Validator {
143
142
  * Reset this validator to it's initial state.
144
143
  */
145
144
  reset(): void {
146
- this.#cycle++;
147
145
  this.#invalid.value = false;
148
146
  const rules = untrack(() => this.#rules.value);
149
147
  for (let i = 0; i < rules.length; i++) {
@@ -238,7 +236,7 @@ export function ValidationMessage(props: {
238
236
  id?: Expression<string | undefined>;
239
237
  children?: unknown;
240
238
  }): unknown {
241
- const theme = extract(THEME);
239
+ const theme = THEME.current;
242
240
  return <Collapse
243
241
  visible={map(props.visible, v => v ?? true)}
244
242
  alert={props.alert}
@@ -1,5 +1,4 @@
1
- import { ClassValue, Expression, extract, StyleValue } from "rvx";
2
-
1
+ import { ClassValue, Expression, StyleValue } from "rvx";
3
2
  import { THEME } from "../common/theme.js";
4
3
 
5
4
  export function Value(props: {
@@ -8,7 +7,7 @@ export function Value(props: {
8
7
  id?: Expression<string | undefined>;
9
8
  children?: unknown;
10
9
  }): unknown {
11
- const theme = extract(THEME);
10
+ const theme = THEME.current;
12
11
  return <span
13
12
  class={[
14
13
  theme?.value,
package/src/index.tsx CHANGED
@@ -10,8 +10,8 @@ export * from "./components/collapse.js";
10
10
  export * from "./components/column.js";
11
11
  export * from "./components/control-group.js";
12
12
  export * from "./components/dialog.js";
13
- export * from "./components/dropdown.js";
14
13
  export * from "./components/dropdown-input.js";
14
+ export * from "./components/dropdown.js";
15
15
  export * from "./components/flex-space.js";
16
16
  export * from "./components/heading.js";
17
17
  export * from "./components/label.js";
@@ -23,7 +23,7 @@ export * from "./components/popover.js";
23
23
  export * from "./components/radio-buttons.js";
24
24
  export * from "./components/row.js";
25
25
  export * from "./components/scroll-view.js";
26
- export * from "./components/text.js";
27
26
  export * from "./components/text-input.js";
27
+ export * from "./components/text.js";
28
28
  export * from "./components/validation.js";
29
29
  export * from "./components/value.js";
package/src/test.tsx CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./common/theme-test.js";
2
+ export * from "./components/checkbox-test.js";
2
3
  export * from "./components/collapse-test.js";
@@ -12,6 +12,9 @@ $root-size: 14px;
12
12
  font-size: #{math.div(1rem, 16px) * $root-size};
13
13
  line-height: 1;
14
14
 
15
+ --accent: rgb(0, 192, 255);
16
+ accent-color: var(--accent);
17
+
15
18
  --content-column-gap: #{px(16)};
16
19
  --content-row-gap: #{px(16)};
17
20
  --content-radius: #{px(8)};
@@ -20,8 +23,9 @@ $root-size: 14px;
20
23
 
21
24
  --control-column-gap: #{px(8)};
22
25
  --control-row-gap: #{px(8)};
23
- --control-radius: #{px(4)};
24
- --control-border: #{px(1)};
26
+ --control-radius: #{px(5)};
27
+ --control-border: #{px(2)};
28
+ --control-shadow: 0 0 #{px(3)} rgba(0, 0, 0, .5);
25
29
  --control-disabled: opacity(.5);
26
30
  @include common.define-quad(control-pad, px(8), px(10));
27
31
 
@@ -33,17 +37,18 @@ $root-size: 14px;
33
37
  --space-gap: #{px(6)};
34
38
 
35
39
  --layout-transition: .15s ease;
40
+ --color-transition: .1s ease;
36
41
  }
37
42
 
38
43
  @include common.theme((
39
44
  bg: (
40
- dark: rgb(32, 32, 32),
45
+ dark: rgb(36, 36, 36),
41
46
  ),
42
47
  fg: (
43
48
  dark: white,
44
49
  ),
45
50
  focus-outline: (
46
- dark: var(--control-border) dashed rgb(0, 127, 255),
51
+ dark: var(--control-border) dashed var(--accent),
47
52
  ),
48
53
  ));
49
54
 
@@ -65,5 +70,5 @@ body {
65
70
  }
66
71
 
67
72
  ::selection {
68
- background-color: rgba(0, 100, 200, .7);
73
+ background-color: rgba(0, 150, 200, .6);
69
74
  }