@rvx/ui 0.1.13 → 0.1.14

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 (94) hide show
  1. package/dist/common/theme.d.ts +10 -0
  2. package/dist/components/button.js +3 -2
  3. package/dist/components/button.js.map +1 -1
  4. package/dist/components/card.d.ts +1 -0
  5. package/dist/components/card.js +6 -3
  6. package/dist/components/card.js.map +1 -1
  7. package/dist/components/checkbox.js +6 -6
  8. package/dist/components/checkbox.js.map +1 -1
  9. package/dist/components/collapse.d.ts +16 -2
  10. package/dist/components/collapse.js +85 -4
  11. package/dist/components/collapse.js.map +1 -1
  12. package/dist/components/column.d.ts +1 -0
  13. package/dist/components/column.js +1 -0
  14. package/dist/components/column.js.map +1 -1
  15. package/dist/components/dialog.d.ts +1 -2
  16. package/dist/components/dialog.js +3 -5
  17. package/dist/components/dialog.js.map +1 -1
  18. package/dist/components/dropdown-input.js +2 -2
  19. package/dist/components/dropdown-input.js.map +1 -1
  20. package/dist/components/dropdown.js +2 -2
  21. package/dist/components/dropdown.js.map +1 -1
  22. package/dist/components/label.js +1 -1
  23. package/dist/components/label.js.map +1 -1
  24. package/dist/components/link.js +2 -1
  25. package/dist/components/link.js.map +1 -1
  26. package/dist/components/nav-list.js +2 -1
  27. package/dist/components/nav-list.js.map +1 -1
  28. package/dist/components/popout.d.ts +1 -2
  29. package/dist/components/popout.js +1 -2
  30. package/dist/components/popout.js.map +1 -1
  31. package/dist/components/popover.js +1 -2
  32. package/dist/components/popover.js.map +1 -1
  33. package/dist/components/radio-buttons.js +11 -10
  34. package/dist/components/radio-buttons.js.map +1 -1
  35. package/dist/components/slider.js +1 -2
  36. package/dist/components/slider.js.map +1 -1
  37. package/dist/components/tabs.d.ts +10 -0
  38. package/dist/components/tabs.js +31 -0
  39. package/dist/components/tabs.js.map +1 -0
  40. package/dist/components/text-input.js +5 -4
  41. package/dist/components/text-input.js.map +1 -1
  42. package/dist/components/validation-rules.d.ts +11 -0
  43. package/dist/components/validation-rules.js +37 -0
  44. package/dist/components/validation-rules.js.map +1 -0
  45. package/dist/components/validation.d.ts +53 -77
  46. package/dist/components/validation.js +117 -95
  47. package/dist/components/validation.js.map +1 -1
  48. package/dist/index.d.ts +2 -3
  49. package/dist/index.js +2 -3
  50. package/dist/index.js.map +1 -1
  51. package/dist/theme.module.css +75 -0
  52. package/dist/theme.module.css.map +1 -1
  53. package/package.json +3 -3
  54. package/src/common/theme.tsx +11 -0
  55. package/src/components/button.tsx +3 -2
  56. package/src/components/card.tsx +10 -5
  57. package/src/components/checkbox.tsx +6 -6
  58. package/src/components/collapse.tsx +127 -5
  59. package/src/components/column.tsx +2 -0
  60. package/src/components/dialog.tsx +3 -5
  61. package/src/components/dropdown-input.tsx +2 -2
  62. package/src/components/dropdown.tsx +2 -2
  63. package/src/components/label.tsx +1 -3
  64. package/src/components/link.tsx +2 -1
  65. package/src/components/nav-list.tsx +2 -1
  66. package/src/components/popout.tsx +1 -2
  67. package/src/components/popover.tsx +1 -2
  68. package/src/components/radio-buttons.tsx +21 -20
  69. package/src/components/slider.tsx +1 -2
  70. package/src/components/tabs.tsx +67 -0
  71. package/src/components/text-input.tsx +5 -4
  72. package/src/components/validation-rules.tsx +50 -0
  73. package/src/components/validation.tsx +175 -177
  74. package/src/index.tsx +2 -3
  75. package/src/theme/base.scss +7 -0
  76. package/src/theme/components/card.scss +4 -1
  77. package/src/theme/components/checkbox.scss +5 -0
  78. package/src/theme/components/column.scss +5 -0
  79. package/src/theme/components/radio-buttons.scss +5 -0
  80. package/src/theme/components/slider.scss +1 -0
  81. package/src/theme/components/tabs.scss +72 -0
  82. package/src/theme/theme.scss +1 -0
  83. package/dist/common/debounce.d.ts +0 -12
  84. package/dist/common/debounce.js +0 -23
  85. package/dist/common/debounce.js.map +0 -1
  86. package/dist/common/parsers.d.ts +0 -88
  87. package/dist/common/parsers.js +0 -62
  88. package/dist/common/parsers.js.map +0 -1
  89. package/dist/common/trim.d.ts +0 -12
  90. package/dist/common/trim.js +0 -16
  91. package/dist/common/trim.js.map +0 -1
  92. package/src/common/debounce.tsx +0 -36
  93. package/src/common/parsers.tsx +0 -167
  94. package/src/common/trim.tsx +0 -30
@@ -1,88 +0,0 @@
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 = $(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">;
@@ -1,62 +0,0 @@
1
- import { $, 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 = $(parser.format(source.value));
8
- }
9
- const invalid = $(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
@@ -1 +0,0 @@
1
- {"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/common/parsers.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAU,YAAY,EAAE,MAAM,KAAK,CAAC;AAE9C,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,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,CAAgC,SAAS,CAAC,CAAC;IAE5D,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"}
@@ -1,12 +0,0 @@
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>;
@@ -1,16 +0,0 @@
1
- import { $, watchUpdates } from "rvx";
2
- import { validatorFor } from "../components/validation.js";
3
- export function trim(source) {
4
- const input = $(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
@@ -1 +0,0 @@
1
- {"version":3,"file":"trim.js","sourceRoot":"","sources":["../../src/common/trim.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAU,YAAY,EAAE,MAAM,KAAK,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAY3D,MAAM,UAAU,IAAI,CAAC,MAAsB;IAC1C,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE9B,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"}
@@ -1,36 +0,0 @@
1
- import { $, Signal, teardown, watchUpdates } from "rvx";
2
- import { validatorFor } from "../components/validation.js";
3
-
4
- /**
5
- * Create a signal that debounces input changes.
6
- *
7
- * This supports validation.
8
- *
9
- * @example
10
- * ```tsx
11
- * <TextInput value={someSignal.pipe(debounce, 500)} />
12
- * ```
13
- */
14
- export function debounce<T>(source: Signal<T>, delay: number): Signal<T> {
15
- const input = $(source.value);
16
- let timer: number | undefined;
17
-
18
- watchUpdates(input, value => {
19
- clearTimeout(timer);
20
- if (source.value !== value) {
21
- timer = (setTimeout as typeof window.setTimeout)(() => {
22
- source.value = value;
23
- }, delay);
24
- teardown(() => {
25
- clearTimeout(timer);
26
- });
27
- }
28
- });
29
-
30
- watchUpdates(source, value => {
31
- input.value = value;
32
- });
33
-
34
- validatorFor(source)?.attach(input);
35
- return input;
36
- }
@@ -1,167 +0,0 @@
1
- import { $, Signal, watchUpdates } from "rvx";
2
-
3
- import { Validator } from "../components/validation.js";
4
-
5
- export interface ValidParseResult<S> {
6
- type: "valid";
7
-
8
- /**
9
- * The parsed value.
10
- */
11
- value: S;
12
- }
13
-
14
- export interface InvalidParseResult<M> {
15
- type: "invalid";
16
-
17
- /**
18
- * The validation message key.
19
- */
20
- value: M;
21
- }
22
-
23
- export type ParseResult<S, M> = ValidParseResult<S> | InvalidParseResult<M>;
24
-
25
- export class ParserFormatError extends TypeError {}
26
-
27
- export interface Parser<S, I, M extends string> {
28
- /**
29
- * Parse the specified input.
30
- */
31
- parse(input: I): ParseResult<S, M>;
32
-
33
- /**
34
- * Format the specified source.
35
- *
36
- * @throws A {@link ParserFormatError} if the source isn't currently formattable.
37
- */
38
- format(source: S): I;
39
-
40
- /**
41
- * An object with validation message keys and content to display.
42
- */
43
- messages: Record<M, unknown>;
44
- }
45
-
46
- /**
47
- * Utility to get the source type from a parser.
48
- */
49
- export type ParserSource<P extends Parser<any, any, any>> = P extends Parser<infer S, any, any> ? S : never;
50
-
51
- /**
52
- * Utility to get the input type from a parser.
53
- */
54
- export type ParserInput<P extends Parser<any, any, any>> = P extends Parser<any, infer I, any> ? I : never;
55
-
56
- /**
57
- * Utility to get the message keys type from a parser.
58
- */
59
- export type ParserMessages<P extends Parser<any, any, any>> = P extends Parser<any, any, infer M> ? M : never;
60
-
61
- /**
62
- * Create a bi-directional input signal with validation.
63
- *
64
- * @param source The source signal.
65
- * @param parser The parser to use.
66
- * @param input The initial input signal to use. If not specified, the parser is used to format the current source value.
67
- *
68
- * @example
69
- * ```tsx
70
- * const value = $(0);
71
- *
72
- * // Format the current value as initial value:
73
- * <TextInput value={
74
- * value
75
- * .pipe(parse, intParser({ format: "Enter a valid number." }))
76
- * .pipe(trim)
77
- * } />
78
- * ```
79
- */
80
- export function parse<S, P extends Parser<S, any, any>>(source: Signal<S>, parser: P, input?: Signal<ParserInput<P>>): Signal<ParserInput<P>> {
81
- if (input === undefined) {
82
- input = $(parser.format(source.value));
83
- }
84
-
85
- const invalid = $<undefined | ParserMessages<P>>(undefined);
86
-
87
- watchUpdates(source, value => {
88
- try {
89
- input!.value = parser.format(value) as ParserInput<P>;
90
- } catch (error) {
91
- if (!(error instanceof ParserFormatError)) {
92
- throw error;
93
- }
94
- }
95
- });
96
-
97
- watchUpdates(input, value => {
98
- const result = parser.parse(value);
99
- if (result.type === "valid") {
100
- source.value = result.value;
101
- invalid.value = undefined;
102
- } else {
103
- invalid.value = result.value as ParserMessages<P>;
104
- }
105
- });
106
-
107
- const validator = Validator.attach(source);
108
- validator.attach(input);
109
-
110
- for (const key in parser.messages) {
111
- validator.prependRule({
112
- validate: () => invalid.value !== key,
113
- message: parser.messages[key],
114
- });
115
- }
116
-
117
- return input;
118
- }
119
-
120
- export interface IntParserOptions {
121
- /**
122
- * A function to check if the parsed value is in a valid range.
123
- *
124
- * By default, the value must be a safe integer.
125
- */
126
- testRange?: (value: number) => boolean;
127
-
128
- /**
129
- * A validation message if the format is invalid.
130
- */
131
- format: unknown;
132
-
133
- /**
134
- * A validation message if the parsed value is out of range.
135
- *
136
- * By default, the format validation message is used.
137
- */
138
- range?: unknown;
139
- }
140
-
141
- /**
142
- * Create a parser for integers for use with {@link parse}.
143
- */
144
- export function intParser(options: IntParserOptions): Parser<number, string, "format" | "range"> {
145
- const range = options.testRange ?? Number.isSafeInteger;
146
- return {
147
- parse(input) {
148
- if (!/^-?\d+$/.test(input)) {
149
- return { type: "invalid", value: "format" };
150
- }
151
- const value = Number(input);
152
- if (!range(value)) {
153
- return { type: "invalid", value: "range" };
154
- }
155
- return { type: "valid", value };
156
- },
157
-
158
- format(source) {
159
- return String(source);
160
- },
161
-
162
- messages: {
163
- format: options.format,
164
- range: options.range ?? options.format,
165
- },
166
- };
167
- }
@@ -1,30 +0,0 @@
1
- import { $, Signal, watchUpdates } from "rvx";
2
-
3
- import { validatorFor } from "../components/validation.js";
4
-
5
- /**
6
- * Create a signal that trims input.
7
- *
8
- * This supports validation.
9
- *
10
- * @example
11
- * ```tsx
12
- * <TextInput value={someSignal.pipe(trim)} />;
13
- * ```
14
- */
15
- export function trim(source: Signal<string>): Signal<string> {
16
- const input = $(source.value);
17
-
18
- watchUpdates(input, value => {
19
- source.value = value.trim();
20
- });
21
-
22
- watchUpdates(source, value => {
23
- if (value !== input.value.trim()) {
24
- input.value = value;
25
- }
26
- });
27
-
28
- validatorFor(source)?.attach(input);
29
- return input;
30
- }