@rvx/ui 0.1.6

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 (159) hide show
  1. package/LICENSE +21 -0
  2. package/dist/common/events.d.ts +72 -0
  3. package/dist/common/events.js +58 -0
  4. package/dist/common/events.js.map +1 -0
  5. package/dist/common/parsers.d.ts +88 -0
  6. package/dist/common/parsers.js +62 -0
  7. package/dist/common/parsers.js.map +1 -0
  8. package/dist/common/theme-test.d.ts +7 -0
  9. package/dist/common/theme-test.js +14 -0
  10. package/dist/common/theme-test.js.map +1 -0
  11. package/dist/common/theme.d.ts +144 -0
  12. package/dist/common/theme.js +2 -0
  13. package/dist/common/theme.js.map +1 -0
  14. package/dist/common/trim.d.ts +12 -0
  15. package/dist/common/trim.js +16 -0
  16. package/dist/common/trim.js.map +1 -0
  17. package/dist/common/types.d.ts +13 -0
  18. package/dist/common/types.js +10 -0
  19. package/dist/common/types.js.map +1 -0
  20. package/dist/common/writing-mode.d.ts +82 -0
  21. package/dist/common/writing-mode.js +61 -0
  22. package/dist/common/writing-mode.js.map +1 -0
  23. package/dist/components/button.d.ts +42 -0
  24. package/dist/components/button.js +26 -0
  25. package/dist/components/button.js.map +1 -0
  26. package/dist/components/checkbox.d.ts +9 -0
  27. package/dist/components/checkbox.js +32 -0
  28. package/dist/components/checkbox.js.map +1 -0
  29. package/dist/components/collapse-test.d.ts +8 -0
  30. package/dist/components/collapse-test.js +15 -0
  31. package/dist/components/collapse-test.js.map +1 -0
  32. package/dist/components/collapse.d.ts +13 -0
  33. package/dist/components/collapse.js +44 -0
  34. package/dist/components/collapse.js.map +1 -0
  35. package/dist/components/column.d.ts +12 -0
  36. package/dist/components/column.js +12 -0
  37. package/dist/components/column.js.map +1 -0
  38. package/dist/components/control-group.d.ts +7 -0
  39. package/dist/components/control-group.js +11 -0
  40. package/dist/components/control-group.js.map +1 -0
  41. package/dist/components/dialog.d.ts +33 -0
  42. package/dist/components/dialog.js +67 -0
  43. package/dist/components/dialog.js.map +1 -0
  44. package/dist/components/dropdown-input.d.ts +27 -0
  45. package/dist/components/dropdown-input.js +31 -0
  46. package/dist/components/dropdown-input.js.map +1 -0
  47. package/dist/components/dropdown.d.ts +123 -0
  48. package/dist/components/dropdown.js +176 -0
  49. package/dist/components/dropdown.js.map +1 -0
  50. package/dist/components/flex-space.d.ts +4 -0
  51. package/dist/components/flex-space.js +10 -0
  52. package/dist/components/flex-space.js.map +1 -0
  53. package/dist/components/heading.d.ts +9 -0
  54. package/dist/components/heading.js +14 -0
  55. package/dist/components/heading.js.map +1 -0
  56. package/dist/components/label.d.ts +14 -0
  57. package/dist/components/label.js +15 -0
  58. package/dist/components/label.js.map +1 -0
  59. package/dist/components/layer.d.ts +81 -0
  60. package/dist/components/layer.js +164 -0
  61. package/dist/components/layer.js.map +1 -0
  62. package/dist/components/link.d.ts +57 -0
  63. package/dist/components/link.js +26 -0
  64. package/dist/components/link.js.map +1 -0
  65. package/dist/components/page.d.ts +9 -0
  66. package/dist/components/page.js +17 -0
  67. package/dist/components/page.js.map +1 -0
  68. package/dist/components/popout.d.ts +134 -0
  69. package/dist/components/popout.js +259 -0
  70. package/dist/components/popout.js.map +1 -0
  71. package/dist/components/popover.d.ts +139 -0
  72. package/dist/components/popover.js +101 -0
  73. package/dist/components/popover.js.map +1 -0
  74. package/dist/components/radio-buttons.d.ts +17 -0
  75. package/dist/components/radio-buttons.js +26 -0
  76. package/dist/components/radio-buttons.js.map +1 -0
  77. package/dist/components/row.d.ts +10 -0
  78. package/dist/components/row.js +23 -0
  79. package/dist/components/row.js.map +1 -0
  80. package/dist/components/scroll-view.d.ts +6 -0
  81. package/dist/components/scroll-view.js +72 -0
  82. package/dist/components/scroll-view.js.map +1 -0
  83. package/dist/components/text-input.d.ts +53 -0
  84. package/dist/components/text-input.js +35 -0
  85. package/dist/components/text-input.js.map +1 -0
  86. package/dist/components/text.d.ts +7 -0
  87. package/dist/components/text.js +11 -0
  88. package/dist/components/text.js.map +1 -0
  89. package/dist/components/validation.d.ts +109 -0
  90. package/dist/components/validation.js +151 -0
  91. package/dist/components/validation.js.map +1 -0
  92. package/dist/components/value.d.ts +7 -0
  93. package/dist/components/value.js +11 -0
  94. package/dist/components/value.js.map +1 -0
  95. package/dist/index.d.ts +29 -0
  96. package/dist/index.js +30 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/test.d.ts +2 -0
  99. package/dist/test.js +3 -0
  100. package/dist/test.js.map +1 -0
  101. package/dist/theme.module.css +679 -0
  102. package/dist/theme.module.css.map +1 -0
  103. package/package.json +29 -0
  104. package/src/common/events.tsx +130 -0
  105. package/src/common/parsers.tsx +167 -0
  106. package/src/common/theme-test.tsx +20 -0
  107. package/src/common/theme.tsx +165 -0
  108. package/src/common/trim.tsx +30 -0
  109. package/src/common/types.tsx +23 -0
  110. package/src/common/writing-mode.tsx +150 -0
  111. package/src/components/button.tsx +94 -0
  112. package/src/components/checkbox.tsx +64 -0
  113. package/src/components/collapse-test.tsx +23 -0
  114. package/src/components/collapse.tsx +75 -0
  115. package/src/components/column.tsx +28 -0
  116. package/src/components/control-group.tsx +22 -0
  117. package/src/components/dialog.tsx +137 -0
  118. package/src/components/dropdown-input.tsx +82 -0
  119. package/src/components/dropdown.tsx +352 -0
  120. package/src/components/flex-space.tsx +15 -0
  121. package/src/components/heading.tsx +23 -0
  122. package/src/components/label.tsx +37 -0
  123. package/src/components/layer.tsx +299 -0
  124. package/src/components/link.tsx +118 -0
  125. package/src/components/page.tsx +36 -0
  126. package/src/components/popout.tsx +461 -0
  127. package/src/components/popover.tsx +292 -0
  128. package/src/components/radio-buttons.tsx +81 -0
  129. package/src/components/row.tsx +37 -0
  130. package/src/components/scroll-view.tsx +97 -0
  131. package/src/components/text-input.tsx +117 -0
  132. package/src/components/text.tsx +22 -0
  133. package/src/components/validation.tsx +272 -0
  134. package/src/components/value.tsx +22 -0
  135. package/src/index.tsx +29 -0
  136. package/src/test.tsx +2 -0
  137. package/src/theme/base.scss +69 -0
  138. package/src/theme/common.scss +51 -0
  139. package/src/theme/components/button.scss +116 -0
  140. package/src/theme/components/checkbox.scss +25 -0
  141. package/src/theme/components/collapse.scss +64 -0
  142. package/src/theme/components/column.scss +28 -0
  143. package/src/theme/components/control-group.scss +14 -0
  144. package/src/theme/components/dialog.scss +44 -0
  145. package/src/theme/components/dropdown.scss +50 -0
  146. package/src/theme/components/flex-space.scss +6 -0
  147. package/src/theme/components/heading.scss +39 -0
  148. package/src/theme/components/label.scss +24 -0
  149. package/src/theme/components/link.scss +25 -0
  150. package/src/theme/components/page.scss +22 -0
  151. package/src/theme/components/popover.scss +58 -0
  152. package/src/theme/components/radio-buttons.scss +31 -0
  153. package/src/theme/components/row.scss +17 -0
  154. package/src/theme/components/scroll-view.scss +51 -0
  155. package/src/theme/components/text-input.scss +45 -0
  156. package/src/theme/components/text.scss +12 -0
  157. package/src/theme/components/validation.scss +15 -0
  158. package/src/theme/components/value.scss +4 -0
  159. package/src/theme/theme.scss +22 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Max J. Polster
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Get an identifier for the pressed key including any modifiers.
3
+ *
4
+ * The identifier is constructed by concatenating the modifies and lower cased key. In addition, the space key is represented as `space` for better readability.
5
+ *
6
+ * Modifiers in order:
7
+ * + `ctrl+`
8
+ * + `shift+`
9
+ * + `alt+`
10
+ * + `meta+`
11
+ *
12
+ * Examples:
13
+ * + `shift+a`
14
+ * + `ctrl+shift+space`
15
+ *
16
+ * @returns The identifier.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * switch (keyFor(event)) {
21
+ * case "enter": ...
22
+ * case "ctrl+a": ...
23
+ * }
24
+ * ```
25
+ */
26
+ export declare function keyFor(event: KeyboardEvent): string;
27
+ /**
28
+ * A function to run an optionally async user action.
29
+ *
30
+ * Returning false indicates, that no action has been performed and that another action or the browser default behavior can be run.
31
+ */
32
+ export type Action<T extends unknown[] = []> = (event: Event, ...args: T) => void | boolean | Promise<void>;
33
+ /**
34
+ * Call an action that was triggered by the specified event.
35
+ */
36
+ export declare function handleActionEvent<T extends unknown[]>(event: Event, action: Action<T>, ...args: T): boolean;
37
+ /**
38
+ * Run an action of the event target is hovered for a minimum duration.
39
+ *
40
+ * @param event The "mouseenter" event.
41
+ * @param action The action to run.
42
+ * @param delay The delay to wait for.
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * <button on:mouseenter={event => {
47
+ * startDelayedHoverOnMouseenter(event, () => {
48
+ * // Close things like popovers or dropdowns in the same context
49
+ * // when this button was hovered for some time:
50
+ * event.target.dispatchEvent(createPassiveActionEvent());
51
+ * });
52
+ * }}>Hover me!</button>
53
+ * ```
54
+ */
55
+ export declare function startDelayedHoverOnMouseenter(event: MouseEvent, action: () => void, delay?: number): void;
56
+ /**
57
+ * Rvx-ui's passive action event name.
58
+ *
59
+ * + This can be dispatched from an element to indicate that the user is likely no longer interested in interacting with other elements in the same context.
60
+ * + This is currently used to close nested dropdowns when the user hovers another dropdown item in the parent for some time.
61
+ */
62
+ export declare const PASSIVE_ACTION_EVENT = "rvx-ui:passive-action";
63
+ /**
64
+ * Create a {@link PASSIVE_ACTION_EVENT} custom event.
65
+ *
66
+ * This event does not bubble.
67
+ */
68
+ export declare function createPassiveActionEvent(): Event;
69
+ /**
70
+ * Debounce an event handler.
71
+ */
72
+ export declare function debounceEvent<T>(delayMs: number, handler: (event: T) => void): (event: T) => void;
@@ -0,0 +1,58 @@
1
+ import { waitFor } from "rvx/async";
2
+ export function keyFor(event) {
3
+ let key = event.key.toLowerCase();
4
+ if (key === " ") {
5
+ key = "space";
6
+ }
7
+ if (event.metaKey) {
8
+ key = "meta+" + key;
9
+ }
10
+ if (event.altKey) {
11
+ key = "alt+" + key;
12
+ }
13
+ if (event.shiftKey) {
14
+ key = "shift+" + key;
15
+ }
16
+ if (event.ctrlKey) {
17
+ key = "ctrl+" + key;
18
+ }
19
+ return key;
20
+ }
21
+ export function handleActionEvent(event, action, ...args) {
22
+ const result = action(event, ...args);
23
+ if (result === false) {
24
+ return false;
25
+ }
26
+ event.preventDefault();
27
+ event.stopImmediatePropagation();
28
+ if (result instanceof Promise) {
29
+ waitFor(result);
30
+ }
31
+ return true;
32
+ }
33
+ export function startDelayedHoverOnMouseenter(event, action, delay = 300) {
34
+ const timer = setTimeout(action, delay);
35
+ const cancel = () => {
36
+ event.target?.removeEventListener("mouseleave", cancel);
37
+ event.target?.removeEventListener("mousedown", cancel, { capture: true });
38
+ event.target?.removeEventListener("touchstart", cancel, { capture: true });
39
+ clearTimeout(timer);
40
+ };
41
+ event.target?.addEventListener("mouseleave", cancel);
42
+ event.target?.addEventListener("mousedown", cancel, { capture: true });
43
+ event.target?.addEventListener("touchstart", cancel, { capture: true });
44
+ }
45
+ export const PASSIVE_ACTION_EVENT = "rvx-ui:passive-action";
46
+ export function createPassiveActionEvent() {
47
+ return new CustomEvent(PASSIVE_ACTION_EVENT);
48
+ }
49
+ export function debounceEvent(delayMs, handler) {
50
+ let timer;
51
+ return event => {
52
+ if (timer) {
53
+ clearTimeout(timer);
54
+ }
55
+ timer = setTimeout(() => handler(event), delayMs);
56
+ };
57
+ }
58
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/common/events.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { Signal } from "rvx";
2
+ export interface ValidParseResult<S> {
3
+ type: "valid";
4
+ /**
5
+ * The parsed value.
6
+ */
7
+ value: S;
8
+ }
9
+ export interface InvalidParseResult<M> {
10
+ type: "invalid";
11
+ /**
12
+ * The validation message key.
13
+ */
14
+ value: M;
15
+ }
16
+ export type ParseResult<S, M> = ValidParseResult<S> | InvalidParseResult<M>;
17
+ export declare class ParserFormatError extends TypeError {
18
+ }
19
+ export interface Parser<S, I, M extends string> {
20
+ /**
21
+ * Parse the specified input.
22
+ */
23
+ parse(input: I): ParseResult<S, M>;
24
+ /**
25
+ * Format the specified source.
26
+ *
27
+ * @throws A {@link ParserFormatError} if the source isn't currently formattable.
28
+ */
29
+ format(source: S): I;
30
+ /**
31
+ * An object with validation message keys and content to display.
32
+ */
33
+ messages: Record<M, unknown>;
34
+ }
35
+ /**
36
+ * Utility to get the source type from a parser.
37
+ */
38
+ export type ParserSource<P extends Parser<any, any, any>> = P extends Parser<infer S, any, any> ? S : never;
39
+ /**
40
+ * Utility to get the input type from a parser.
41
+ */
42
+ export type ParserInput<P extends Parser<any, any, any>> = P extends Parser<any, infer I, any> ? I : never;
43
+ /**
44
+ * Utility to get the message keys type from a parser.
45
+ */
46
+ export type ParserMessages<P extends Parser<any, any, any>> = P extends Parser<any, any, infer M> ? M : never;
47
+ /**
48
+ * Create a bi-directional input signal with validation.
49
+ *
50
+ * @param source The source signal.
51
+ * @param parser The parser to use.
52
+ * @param input The initial input signal to use. If not specified, the parser is used to format the current source value.
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * const value = sig(0);
57
+ *
58
+ * // Format the current value as initial value:
59
+ * <TextInput value={
60
+ * value
61
+ * .pipe(parse, intParser({ format: "Enter a valid number." }))
62
+ * .pipe(trim)
63
+ * } />
64
+ * ```
65
+ */
66
+ export declare function parse<S, P extends Parser<S, any, any>>(source: Signal<S>, parser: P, input?: Signal<ParserInput<P>>): Signal<ParserInput<P>>;
67
+ export interface IntParserOptions {
68
+ /**
69
+ * A function to check if the parsed value is in a valid range.
70
+ *
71
+ * By default, the value must be a safe integer.
72
+ */
73
+ testRange?: (value: number) => boolean;
74
+ /**
75
+ * A validation message if the format is invalid.
76
+ */
77
+ format: unknown;
78
+ /**
79
+ * A validation message if the parsed value is out of range.
80
+ *
81
+ * By default, the format validation message is used.
82
+ */
83
+ range?: unknown;
84
+ }
85
+ /**
86
+ * Create a parser for integers for use with {@link parse}.
87
+ */
88
+ export declare function intParser(options: IntParserOptions): Parser<number, string, "format" | "range">;
@@ -0,0 +1,62 @@
1
+ import { sig, watchUpdates } from "rvx";
2
+ import { Validator } from "../components/validation.js";
3
+ export class ParserFormatError extends TypeError {
4
+ }
5
+ export function parse(source, parser, input) {
6
+ if (input === undefined) {
7
+ input = sig(parser.format(source.value));
8
+ }
9
+ const invalid = sig(undefined);
10
+ watchUpdates(source, value => {
11
+ try {
12
+ input.value = parser.format(value);
13
+ }
14
+ catch (error) {
15
+ if (!(error instanceof ParserFormatError)) {
16
+ throw error;
17
+ }
18
+ }
19
+ });
20
+ watchUpdates(input, value => {
21
+ const result = parser.parse(value);
22
+ if (result.type === "valid") {
23
+ source.value = result.value;
24
+ invalid.value = undefined;
25
+ }
26
+ else {
27
+ invalid.value = result.value;
28
+ }
29
+ });
30
+ const validator = Validator.attach(source);
31
+ validator.attach(input);
32
+ for (const key in parser.messages) {
33
+ validator.prependRule({
34
+ validate: () => invalid.value !== key,
35
+ message: parser.messages[key],
36
+ });
37
+ }
38
+ return input;
39
+ }
40
+ export function intParser(options) {
41
+ const range = options.testRange ?? Number.isSafeInteger;
42
+ return {
43
+ parse(input) {
44
+ if (!/^-?\d+$/.test(input)) {
45
+ return { type: "invalid", value: "format" };
46
+ }
47
+ const value = Number(input);
48
+ if (!range(value)) {
49
+ return { type: "invalid", value: "range" };
50
+ }
51
+ return { type: "valid", value };
52
+ },
53
+ format(source) {
54
+ return String(source);
55
+ },
56
+ messages: {
57
+ format: options.format,
58
+ range: options.range ?? options.format,
59
+ },
60
+ };
61
+ }
62
+ //# sourceMappingURL=parsers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/common/parsers.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAU,YAAY,EAAE,MAAM,KAAK,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAsBxD,MAAM,OAAO,iBAAkB,SAAQ,SAAS;CAAG;AAuDnD,MAAM,UAAU,KAAK,CAAmC,MAAiB,EAAE,MAAS,EAAE,KAA8B;IACnH,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAgC,SAAS,CAAC,CAAC;IAE9D,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;QAC5B,IAAI,CAAC;YACJ,KAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAmB,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,KAAK,YAAY,iBAAiB,CAAC,EAAE,CAAC;gBAC3C,MAAM,KAAK,CAAC;YACb,CAAC;QACF,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;QAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC7B,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC5B,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC;QAC3B,CAAC;aAAM,CAAC;YACP,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAA0B,CAAC;QACnD,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3C,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAExB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACnC,SAAS,CAAC,WAAW,CAAC;YACrB,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,GAAG;YACrC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;SAC7B,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AA0BD,MAAM,UAAU,SAAS,CAAC,OAAyB;IAClD,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC,aAAa,CAAC;IACxD,OAAO;QACN,KAAK,CAAC,KAAK;YACV,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;YAC7C,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnB,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;YAC5C,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACjC,CAAC;QAED,MAAM,CAAC,MAAM;YACZ,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QAED,QAAQ,EAAE;YACT,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM;SACtC;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Theme } from "./theme.js";
2
+ /**
3
+ * Get a class name from the current theme.
4
+ *
5
+ * @throws An error if the current theme doesn't support the specified key.
6
+ */
7
+ export declare function themeClass(key: keyof Theme): string;
@@ -0,0 +1,14 @@
1
+ import { extract } from "rvx";
2
+ import { THEME } from "./theme.js";
3
+ export function themeClass(key) {
4
+ const theme = extract(THEME);
5
+ if (!theme) {
6
+ throw new Error("theme is not available in the current context");
7
+ }
8
+ const value = theme[key];
9
+ if (value === undefined) {
10
+ throw new Error(`${key} is not supported by the current theme`);
11
+ }
12
+ return value;
13
+ }
14
+ //# sourceMappingURL=theme-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-test.js","sourceRoot":"","sources":["../../src/common/theme-test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAE9B,OAAO,EAAE,KAAK,EAAS,MAAM,YAAY,CAAC;AAO1C,MAAM,UAAU,UAAU,CAAC,GAAgB;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,wCAAwC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC"}
@@ -0,0 +1,144 @@
1
+ import { ContextKey } from "rvx";
2
+ export declare const THEME: ContextKey<Theme>;
3
+ /**
4
+ * A collection of class names that is used as the theme.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * import { mount, Inject } from "rvx";
9
+ * import { THEME, Button } from "@rvx/ui";
10
+ *
11
+ * import theme from "./theme.module.css";
12
+ *
13
+ * mount(
14
+ * document.body,
15
+ * <Inject key={THEME} value={theme}>
16
+ * {() => <>
17
+ * <Button>Click me!</Button>
18
+ * </>}
19
+ * </Inject>
20
+ * );
21
+ * ```
22
+ */
23
+ export interface Theme {
24
+ /** Class for all buttons */
25
+ button?: string;
26
+ /** Additional class for buttons with the "default" variant */
27
+ button_default?: string;
28
+ /** Additional class for buttons with the "primary" variant */
29
+ button_primary?: string;
30
+ /** Additional class for buttons with the "success" variant */
31
+ button_success?: string;
32
+ /** Additional class for buttons with the "danger" variant */
33
+ button_danger?: string;
34
+ /** Additional class for buttons with the "warning" variant */
35
+ button_warning?: string;
36
+ /** Additional class for buttons with the "input" variant */
37
+ button_input?: string;
38
+ /** Class for all checkbox containing labels */
39
+ checkbox_label?: string;
40
+ /** Class for all checkbox inputs */
41
+ checkbox_input?: string;
42
+ /** Class for checkbox text content. This element may also be a text block. */
43
+ checkbox_content?: string;
44
+ /** Class for collapses */
45
+ collapse?: string;
46
+ /** Class for collapses that is when it's size has been measured. */
47
+ collapse_sized?: string;
48
+ /** Class for an additional element between the collapse container and the content. If this is undefined, the element is omitted. */
49
+ collapse_view?: string;
50
+ /** Class that is added to collapses to play an alert animation. */
51
+ collapse_alert?: string;
52
+ /** Additional class for visible collapses */
53
+ collapse_visible?: string;
54
+ /** Class for collapse content */
55
+ collapse_content?: string;
56
+ /** Class for all columns */
57
+ column?: string;
58
+ /** Additional class for columns of content */
59
+ column_content?: string;
60
+ /** Additional class for columns of controls */
61
+ column_control?: string;
62
+ /** Class for all inline control groups */
63
+ control_group?: string;
64
+ /** Class for all dialog containers */
65
+ dialog_container?: string;
66
+ /** Class for all dialog bodies */
67
+ dialog_body?: string;
68
+ /** Class for all dialog footers */
69
+ dialog_footer?: string;
70
+ /** Class for all dropdown roots. */
71
+ dropdown?: string;
72
+ /** Additional class for nested dropdowns. */
73
+ dropdown_expansion?: string;
74
+ /** Class for the dropdown scroll area. */
75
+ dropdown_scroll_area?: string;
76
+ /** Class for the dropdown content. */
77
+ dropdown_content?: string;
78
+ /** Class for all dropdown items. */
79
+ dropdown_item?: string;
80
+ /** Class for the currently active dropdown item. */
81
+ dropdown_item_active?: string;
82
+ /** Class for growing flex space */
83
+ flex_space?: string;
84
+ /** Class for all headings which are also semantic elements like h1, h2 etc. */
85
+ heading?: string;
86
+ /** Class for all labels */
87
+ label?: string;
88
+ /** Class for all links */
89
+ link?: string;
90
+ /** Class for all page roots. */
91
+ page?: string;
92
+ /** Class for page scrollbar size compensation elements. */
93
+ page_scrollbar_comp?: string;
94
+ /** Class for the page content column besides the scrollbar size compensation element. */
95
+ page_content_col?: string;
96
+ /** Class for page content roots. */
97
+ page_content?: string;
98
+ /** Class for all popover roots. */
99
+ popover?: string;
100
+ /** Class for the spike container area. */
101
+ popover_spike_area?: string;
102
+ /** Class for the popover scrollable area. */
103
+ popover_scroll_area?: string;
104
+ /** Class for the spike root. */
105
+ popover_spike?: string;
106
+ /** Class for the popover content. */
107
+ popover_content?: string;
108
+ /** Class for all radio button columns */
109
+ radio_buttons?: string;
110
+ /** Class for all radio button containing labels */
111
+ radio_button_label?: string;
112
+ /** Class for all radio button inputs */
113
+ radio_button_input?: string;
114
+ /** Class for radio button text content. This element may also be a text block. */
115
+ radio_button_content?: string;
116
+ /** Class for all rows */
117
+ row?: string;
118
+ /** Additional class for rows of content */
119
+ row_content?: string;
120
+ /** Additional class for rows of controls */
121
+ row_control?: string;
122
+ /** Class for all scroll view roots */
123
+ scroll_view?: string;
124
+ /** Class for the scrolling area. */
125
+ scroll_view_area?: string;
126
+ /** Class for scroll view content root. */
127
+ scroll_view_content?: string;
128
+ /** Class for scroll view start overflow indicators. */
129
+ scroll_view_indicator_start?: string;
130
+ /** Class for scroll view end overflow indicators. */
131
+ scroll_view_indicator_end?: string;
132
+ /** Class for visible overflow indicators. */
133
+ scroll_view_indicator_visible?: string;
134
+ /** Class for all text inputs */
135
+ text_input?: string;
136
+ /** Class for all text blocks */
137
+ text?: string;
138
+ /** Class for all validation messages */
139
+ validation_message?: string;
140
+ /** Class for all validation message containers. */
141
+ validation_message_container?: string;
142
+ /** Class for all text values */
143
+ value?: string;
144
+ }
@@ -0,0 +1,2 @@
1
+ export const THEME = Symbol.for("rvx-ui:theme");
2
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/common/theme.tsx"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAsB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { Signal } from "rvx";
2
+ /**
3
+ * Create a signal that trims input.
4
+ *
5
+ * This supports validation.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * <TextInput value={someSignal.pipe(trim)} />;
10
+ * ```
11
+ */
12
+ export declare function trim(source: Signal<string>): Signal<string>;
@@ -0,0 +1,16 @@
1
+ import { sig, watchUpdates } from "rvx";
2
+ import { validatorFor } from "../components/validation.js";
3
+ export function trim(source) {
4
+ const input = sig(source.value);
5
+ watchUpdates(input, value => {
6
+ source.value = value.trim();
7
+ });
8
+ watchUpdates(source, value => {
9
+ if (value !== input.value.trim()) {
10
+ input.value = value;
11
+ }
12
+ });
13
+ validatorFor(source)?.attach(input);
14
+ return input;
15
+ }
16
+ //# sourceMappingURL=trim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trim.js","sourceRoot":"","sources":["../../src/common/trim.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAU,YAAY,EAAE,MAAM,KAAK,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAY3D,MAAM,UAAU,IAAI,CAAC,MAAsB;IAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEhC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;QAC3B,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;QAC5B,IAAI,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YAClC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC;AACd,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { Expression } from "rvx";
2
+ export type SizeContext = "content" | "control";
3
+ export type AriaLive = "off" | "polite" | "assertive";
4
+ export type AriaRelevant = "additions" | "removals" | "text" | "all" | "additions removals" | "additions text" | "removals text";
5
+ /**
6
+ * Utility to map expressions of strings or string arrays to (e.g. space) separated strings.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * <a rel={separated(["noreferrer", "author"], " ")} />;
11
+ * ```
12
+ */
13
+ export declare function separated(input: Expression<string | string[] | undefined>, sep: string): Expression<string | undefined>;
@@ -0,0 +1,10 @@
1
+ import { map } from "rvx";
2
+ export function separated(input, sep) {
3
+ return map(input, v => {
4
+ if (Array.isArray(v)) {
5
+ return v.join(sep);
6
+ }
7
+ return v;
8
+ });
9
+ }
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/common/types.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,GAAG,EAAE,MAAM,KAAK,CAAC;AAetC,MAAM,UAAU,SAAS,CAAC,KAAgD,EAAE,GAAW;IACtF,OAAO,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE;QACrB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,CAAC,CAAC;IACV,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * A CSS writing mode property value.
3
+ */
4
+ export type WritingMode = "horizontal-tb" | "vertical-rl" | "vertical-lr" | "sideways-rl" | "sideways-lr";
5
+ /**
6
+ * A CSS script direction property value.
7
+ */
8
+ export type ScriptDirection = "ltr" | "rtl";
9
+ /** The up {@link Direction}. */
10
+ export declare const UP = 0;
11
+ /** The right {@link Direction}. */
12
+ export declare const RIGHT = 1;
13
+ /** The down {@link Direction}. */
14
+ export declare const DOWN = 2;
15
+ /** The left {@link Direction}. */
16
+ export declare const LEFT = 3;
17
+ /**
18
+ * Represents a direction ({@link UP}, {@link RIGHT}, {@link DOWN}, {@link LEFT}).
19
+ */
20
+ export type Direction = typeof UP | typeof RIGHT | typeof DOWN | typeof LEFT;
21
+ /**
22
+ * Can be indexed by a {@link Direction} to get the respective css inset property.
23
+ */
24
+ export declare const INSET: Record<Direction, "top" | "right" | "bottom" | "left">;
25
+ /**
26
+ * Flip a direction.
27
+ */
28
+ export declare function flip(dir: Direction): Direction;
29
+ /**
30
+ * Check if the specified directions are along the same axis.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * axisEquals(UP, UP) // true
35
+ * axisEquals(UP, DOWN) // true
36
+ * axisEquals(UP, RIGHT) // false
37
+ * ```
38
+ */
39
+ export declare function axisEquals(a: Direction, b: Direction): boolean;
40
+ /**
41
+ * Get the window size in CSS pixels along the axis of the specified direction.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * getWindowSize(UP) === window.innerHeight // true
46
+ * getWindowSize(DOWN) === window.innerHeight // true
47
+ * ```
48
+ */
49
+ export declare function getWindowSize(dir: Direction): number;
50
+ export interface DOMRectSize {
51
+ width: number;
52
+ height: number;
53
+ }
54
+ /**
55
+ * Get the size in CSS pixels of a DOM rect along the axis of the specified direction.
56
+ *
57
+ * @example
58
+ * ```tsx
59
+ * getSize(button.getBoundingClientRect(), RIGHT) // 234.5
60
+ * ```
61
+ */
62
+ export declare function getSize(rect: DOMRectSize, dir: Direction): number;
63
+ export interface DOMRectXY {
64
+ x: number;
65
+ y: number;
66
+ }
67
+ /**
68
+ * Get the X/Y coordinate start in CSS pixels of the specified DOM rect along the axis of the specified direction.
69
+ */
70
+ export declare function getXY(rect: DOMRectXY, dir: Direction): number;
71
+ /**
72
+ * Get the block start direction with respect to the specified writing mode.
73
+ */
74
+ export declare function getBlockStart(writingMode: WritingMode): Direction;
75
+ /**
76
+ * Get the inline start direction with respect to the specified writing mode and script direction.
77
+ */
78
+ export declare function getInlineStart(writingMode: WritingMode, scriptDir: ScriptDirection): Direction;
79
+ /**
80
+ * Get the space in CSS pixels between a DOM rect and the window in the specified direction.
81
+ */
82
+ export declare function getWindowSpaceAround(rect: DOMRect, dir: Direction): number;