@manyducks.co/dolla 2.0.0-alpha.6 → 2.0.0-alpha.60

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 (104) hide show
  1. package/README.md +86 -591
  2. package/dist/core/context.d.ts +144 -0
  3. package/dist/core/env.d.ts +3 -0
  4. package/dist/core/index.d.ts +22 -0
  5. package/dist/core/logger.d.ts +42 -0
  6. package/dist/core/markup.d.ts +125 -0
  7. package/dist/core/mount.d.ts +15 -0
  8. package/dist/core/nodes/dom.d.ts +14 -0
  9. package/dist/core/nodes/dynamic.d.ts +29 -0
  10. package/dist/core/nodes/html.d.ts +24 -0
  11. package/dist/core/nodes/portal.d.ts +19 -0
  12. package/dist/core/nodes/repeat.d.ts +25 -0
  13. package/dist/core/nodes/view.d.ts +24 -0
  14. package/dist/core/ref.d.ts +18 -0
  15. package/dist/core/signals.d.ts +43 -0
  16. package/dist/core/symbols.d.ts +2 -0
  17. package/dist/{views → core/views}/default-crash-view.d.ts +6 -2
  18. package/dist/core/views/fragment.d.ts +7 -0
  19. package/dist/fragment-BahD_BJA.js +7 -0
  20. package/dist/fragment-BahD_BJA.js.map +1 -0
  21. package/dist/{modules/http.d.ts → http/index.d.ts} +3 -5
  22. package/dist/http.js +163 -0
  23. package/dist/http.js.map +1 -0
  24. package/dist/i18n/index.d.ts +134 -0
  25. package/dist/i18n.js +318 -0
  26. package/dist/i18n.js.map +1 -0
  27. package/dist/index.js +105 -1385
  28. package/dist/index.js.map +1 -1
  29. package/dist/jsx-dev-runtime.d.ts +3 -2
  30. package/dist/jsx-dev-runtime.js +5 -12
  31. package/dist/jsx-dev-runtime.js.map +1 -1
  32. package/dist/jsx-runtime.d.ts +4 -3
  33. package/dist/jsx-runtime.js +9 -15
  34. package/dist/jsx-runtime.js.map +1 -1
  35. package/dist/logger-MPwl-Xqu.js +524 -0
  36. package/dist/logger-MPwl-Xqu.js.map +1 -0
  37. package/dist/markup-BGlfQYQk.js +996 -0
  38. package/dist/markup-BGlfQYQk.js.map +1 -0
  39. package/dist/router/index.d.ts +2 -0
  40. package/dist/router/router.d.ts +149 -0
  41. package/dist/{routing.d.ts → router/router.utils.d.ts} +17 -3
  42. package/dist/router/router.utils.test.d.ts +1 -0
  43. package/dist/router-BpuJQ6OA.js +516 -0
  44. package/dist/router-BpuJQ6OA.js.map +1 -0
  45. package/dist/router.js +8 -0
  46. package/dist/router.js.map +1 -0
  47. package/dist/typeChecking-CbltMOUt.js +71 -0
  48. package/dist/typeChecking-CbltMOUt.js.map +1 -0
  49. package/dist/typeChecking.d.ts +2 -98
  50. package/dist/typeChecking.test.d.ts +1 -0
  51. package/dist/types.d.ts +98 -25
  52. package/dist/utils.d.ts +20 -3
  53. package/docs/http.md +29 -0
  54. package/docs/i18n.md +43 -0
  55. package/docs/index.md +10 -0
  56. package/docs/markup.md +16 -0
  57. package/docs/mixins.md +32 -0
  58. package/docs/ref.md +93 -0
  59. package/docs/router.md +80 -0
  60. package/docs/setup.md +31 -0
  61. package/docs/signals.md +166 -0
  62. package/docs/state.md +141 -0
  63. package/docs/stores.md +62 -0
  64. package/docs/views.md +208 -0
  65. package/examples/webcomponent/index.html +14 -0
  66. package/examples/webcomponent/main.js +165 -0
  67. package/index.d.ts +2 -2
  68. package/notes/TODO.md +6 -0
  69. package/notes/atomic.md +452 -0
  70. package/notes/context-routes.md +61 -0
  71. package/notes/custom-nodes.md +17 -0
  72. package/notes/effection-idea.md +34 -0
  73. package/notes/elimination.md +33 -0
  74. package/notes/mixins.md +22 -0
  75. package/notes/molecule.md +35 -0
  76. package/notes/observable.md +180 -0
  77. package/notes/readme-scratch.md +45 -7
  78. package/notes/route-middleware.md +42 -0
  79. package/notes/scratch.md +353 -6
  80. package/notes/splitting.md +5 -0
  81. package/notes/stores.md +79 -0
  82. package/package.json +27 -12
  83. package/vite.config.js +5 -11
  84. package/build.js +0 -34
  85. package/dist/index.d.ts +0 -21
  86. package/dist/markup.d.ts +0 -100
  87. package/dist/modules/dolla.d.ts +0 -111
  88. package/dist/modules/language.d.ts +0 -41
  89. package/dist/modules/render.d.ts +0 -17
  90. package/dist/modules/router.d.ts +0 -152
  91. package/dist/nodes/cond.d.ts +0 -26
  92. package/dist/nodes/html.d.ts +0 -31
  93. package/dist/nodes/observer.d.ts +0 -29
  94. package/dist/nodes/outlet.d.ts +0 -22
  95. package/dist/nodes/portal.d.ts +0 -19
  96. package/dist/nodes/repeat.d.ts +0 -34
  97. package/dist/nodes/text.d.ts +0 -19
  98. package/dist/passthrough-CW8Ezjg-.js +0 -1244
  99. package/dist/passthrough-CW8Ezjg-.js.map +0 -1
  100. package/dist/state.d.ts +0 -101
  101. package/dist/view.d.ts +0 -50
  102. package/dist/views/passthrough.d.ts +0 -5
  103. package/tests/state.test.js +0 -135
  104. /package/dist/{routing.test.d.ts → core/signals.test.d.ts} +0 -0
@@ -0,0 +1,71 @@
1
+ function o(r) {
2
+ const t = typeof r;
3
+ switch (t) {
4
+ case "undefined":
5
+ return t;
6
+ case "number":
7
+ return isNaN(r) ? "NaN" : t;
8
+ case "function":
9
+ return /^\s*class\s+/.test(r.toString()) ? "class" : t;
10
+ case "object":
11
+ return r === null ? "null" : r instanceof Promise ? "promise" : r instanceof Map ? "map" : r instanceof Set ? "set" : Array.isArray(r) ? "array" : t;
12
+ default:
13
+ return t;
14
+ }
15
+ }
16
+ function c(r) {
17
+ return Array.isArray(r);
18
+ }
19
+ function u(r, t) {
20
+ return c(t) && t.every((n) => r(n));
21
+ }
22
+ function y(r, t, n) {
23
+ if (u(r, t))
24
+ return !0;
25
+ throw new TypeError(i(t, n));
26
+ }
27
+ function f(r) {
28
+ return typeof r == "string";
29
+ }
30
+ function p(r, t) {
31
+ if (f(r))
32
+ return !0;
33
+ throw new TypeError(i(r, t ?? "Expected a string. Got type: %t, value: %v"));
34
+ }
35
+ function w(r) {
36
+ return o(r) === "function";
37
+ }
38
+ function A(...r) {
39
+ const t = r[0], n = f(r[2]) ? r[2] : `Expected instance of ${t.name}. Got type: %t, value: %v`, s = (e) => {
40
+ if (e instanceof t)
41
+ return !0;
42
+ throw new TypeError(i(e, n));
43
+ };
44
+ return r.length < 2 ? s : s(r[1]);
45
+ }
46
+ function a(r) {
47
+ return r != null && typeof r == "object" && !c(r);
48
+ }
49
+ function g(r, t) {
50
+ if (a(r))
51
+ return !0;
52
+ throw new TypeError(i(r, t));
53
+ }
54
+ function i(r, t) {
55
+ var e;
56
+ const n = o(r), s = ((e = r == null ? void 0 : r.toString) == null ? void 0 : e.call(r)) || String(r);
57
+ return t.replaceAll("%t", n).replaceAll("%v", s);
58
+ }
59
+ export {
60
+ A as a,
61
+ f as b,
62
+ w as c,
63
+ y as d,
64
+ p as e,
65
+ g as f,
66
+ c as g,
67
+ u as h,
68
+ a as i,
69
+ o as t
70
+ };
71
+ //# sourceMappingURL=typeChecking-CbltMOUt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeChecking-CbltMOUt.js","sources":["../src/typeChecking.ts"],"sourcesContent":["type TypeNames =\n // These values can be returned by `typeof`.\n | \"string\"\n | \"number\"\n | \"bigint\"\n | \"boolean\"\n | \"symbol\"\n | \"undefined\"\n | \"object\"\n | \"function\"\n // These values are more specific ones that the `typeOf` function can return.\n | \"null\"\n | \"array\"\n | \"class\"\n | \"promise\"\n | \"map\"\n | \"set\"\n | \"NaN\";\n\n/**\n * Extends `typeof` operator with more specific and useful type distinctions.\n */\nexport function typeOf(value: any): TypeNames {\n const type = typeof value;\n switch (type) {\n case \"undefined\":\n return type;\n case \"number\":\n if (isNaN(value as any)) return \"NaN\";\n return type;\n case \"function\":\n if (/^\\s*class\\s+/.test(value.toString())) return \"class\";\n return type;\n case \"object\":\n if (value === null) return \"null\";\n if (value instanceof Promise) return \"promise\";\n if (value instanceof Map) return \"map\";\n if (value instanceof Set) return \"set\";\n if (Array.isArray(value)) return \"array\";\n return type;\n default:\n return type;\n }\n}\n\n/**\n * Throws a TypeError unless `condition` is truthy.\n *\n * @param condition - Value whose truthiness is in question.\n * @param errorMessage - Optional message for the thrown TypeError.\n */\nexport function assert(condition: any, errorMessage?: string): void {\n if (!condition) {\n throw new TypeError(\n formatError(condition, errorMessage || \"Failed assertion. Value is not truthy. Got type: %t, value: %v\"),\n );\n }\n}\n\n/**\n * Returns true if `value` is an array.\n */\nexport function isArray(value: unknown): value is Array<unknown> {\n return Array.isArray(value);\n}\n\n/**\n * Throws an error if `value` is not an array.\n */\nexport function assertArray(value: unknown, errorMessage?: string): value is Array<unknown> {\n if (isArray(value)) {\n return true;\n }\n\n throw new TypeError(formatError(value, errorMessage || \"Expected array. Got type: %t, value: %v\"));\n}\n\n/**\n * Returns true when `value` is an array and `check` returns true for every item.\n *\n * @param check - Function to check items against.\n * @param value - A possible array.\n */\n\nexport function isArrayOf<T>(check: (item: unknown) => boolean, value: unknown): value is T[] {\n return isArray(value) && value.every((item) => check(item));\n}\n\n/**\n * Throws a TypeError unless `value` is an array and `check` returns true for every item.\n *\n * @param check - Function to check items against.\n * @param value - A possible array.\n * @param errorMessage - A custom error message.\n */\nexport function assertArrayOf<T>(\n check: (item: unknown) => boolean,\n value: unknown,\n errorMessage?: string,\n): value is T[] {\n if (isArrayOf(check, value)) {\n return true;\n }\n\n throw new TypeError(formatError(value, errorMessage ?? \"Expected an array of valid items. Got type: %t, value: %v\"));\n}\n\n/**\n * Returns true if `value` is a string.\n */\nexport function isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\n/**\n * Throws a TypeError unless `value` is a string.\n */\nexport function assertString(value: unknown, errorMessage?: string): value is string {\n if (isString(value)) {\n return true;\n }\n\n throw new TypeError(formatError(value, errorMessage ?? \"Expected a string. Got type: %t, value: %v\"));\n}\n\n// TODO: More specific validation for common types of strings? Email address, URL, UUID, etc?\n\n/**\n * Returns true if `value` is a function (but not a class).\n */\nexport function isFunction<T = (...args: unknown[]) => unknown>(value: unknown): value is T {\n return typeOf(value) === \"function\";\n}\n\n/**\n * Throws a TypeError unless `value` is a function.\n */\nexport function assertFunction<T = (...args: unknown[]) => unknown>(value: unknown, errorMessage?: string): value is T {\n if (isFunction(value)) {\n return true;\n }\n\n throw new TypeError(formatError(value, errorMessage ?? \"Expected a function. Got type: %t, value: %v\"));\n}\n\n/**\n * Returns true if `value` is a number.\n */\nexport function isNumber(value: unknown): value is number {\n return typeof value === \"number\" && !isNaN(value);\n}\n\n/**\n * Throws a TypeError unless `value` is a number.\n */\nexport function assertNumber(value: unknown, errorMessage?: string): value is number {\n if (isNumber(value)) {\n return true;\n }\n\n throw new TypeError(formatError(value, errorMessage ?? \"Expected a number. Got type: %t, value: %v\"));\n}\n\n/**\n * Returns a function that takes a `value` and returns true if `value` is an instance of `constructor`.\n *\n * @param constructor - The constructor a value must be an instance of to match.\n */\nexport function isInstanceOf<T extends Function>(constructor: T): (value: unknown) => value is T;\n\n/**\n * Returns `true` if `value` is an instance of `constructor`.\n *\n * @param constructor - The constructor `value` must be an instance of.\n * @param value - A value that may be an instance of `constructor`.\n */\nexport function isInstanceOf<T extends Function>(constructor: T, value: unknown): value is T;\n\nexport function isInstanceOf<T extends Function>(...args: unknown[]) {\n const constructor = args[0] as T;\n\n const test = (value: unknown): value is T => {\n return value instanceof constructor;\n };\n\n if (args.length < 2) {\n return test;\n } else {\n return test(args[1]);\n }\n}\n\n/**\n * Returns a function that takes a `value` and throws a TypeError unless `value` is an instance of `constructor`.\n *\n * @param constructor - The constructor a value must be an instance of to match.\n */\nexport function assertInstanceOf<T extends Function>(constructor: T): (value: unknown) => value is T;\n\n/**\n * Throws a TypeError unless `value` is an instance of `constructor`.\n *\n * @param constructor - The constructor `value` must be an instance of.\n * @param value - A value that may be an instance of `constructor`.\n * @param errorMessage - A custom error message for when the assertion fails.\n */\nexport function assertInstanceOf<T extends Function>(constructor: T, value: unknown, errorMessage?: string): value is T;\n\nexport function assertInstanceOf<T extends Function>(...args: unknown[]) {\n const constructor = args[0] as T;\n const errorMessage = isString(args[2])\n ? args[2]\n : `Expected instance of ${constructor.name}. Got type: %t, value: %v`;\n\n const test = (value: unknown): value is T => {\n if (value instanceof constructor) {\n return true;\n }\n\n throw new TypeError(formatError(value, errorMessage));\n };\n\n if (args.length < 2) {\n return test;\n } else {\n return test(args[1]);\n }\n}\n\n/**\n * Returns true if `value` is a plain JavaScript object.\n */\nexport function isObject(value: unknown): value is Record<string | number | symbol, unknown> {\n return value != null && typeof value === \"object\" && !isArray(value);\n}\n\n/**\n * Throws a TypeError unless `value` is a plain JavaScript object.\n */\nexport function assertObject(value: unknown, errorMessage?: string): value is object {\n if (isObject(value)) {\n return true;\n }\n\n throw new TypeError(formatError(value, errorMessage ?? \"Expected an object. Got type: %t, value: %v\"));\n}\n\n/**\n * Replaces `%t` and `%v` placeholders in a message with real values.\n */\nfunction formatError(value: unknown, message: string) {\n const typeName = typeOf(value);\n\n // TODO: Pretty format value as string based on type.\n const valueString = value?.toString?.() || String(value);\n\n return message.replaceAll(\"%t\", typeName).replaceAll(\"%v\", valueString);\n}\n"],"names":["typeOf","value","type","isArray","isArrayOf","check","item","assertArrayOf","errorMessage","formatError","isString","assertString","isFunction","assertInstanceOf","args","constructor","test","isObject","assertObject","message","_a","typeName","valueString"],"mappings":"AAsBO,SAASA,EAAOC,GAAuB;AAC5C,QAAMC,IAAO,OAAOD;AACpB,UAAQC,GAAM;AAAA,IACZ,KAAK;AACI,aAAAA;AAAA,IACT,KAAK;AACC,aAAA,MAAMD,CAAY,IAAU,QACzBC;AAAA,IACT,KAAK;AACH,aAAI,eAAe,KAAKD,EAAM,SAAU,CAAA,IAAU,UAC3CC;AAAA,IACT,KAAK;AACC,aAAAD,MAAU,OAAa,SACvBA,aAAiB,UAAgB,YACjCA,aAAiB,MAAY,QAC7BA,aAAiB,MAAY,QAC7B,MAAM,QAAQA,CAAK,IAAU,UAC1BC;AAAA,IACT;AACS,aAAAA;AAAA,EAAA;AAEb;AAmBO,SAASC,EAAQF,GAAyC;AACxD,SAAA,MAAM,QAAQA,CAAK;AAC5B;AAoBgB,SAAAG,EAAaC,GAAmCJ,GAA8B;AACrF,SAAAE,EAAQF,CAAK,KAAKA,EAAM,MAAM,CAACK,MAASD,EAAMC,CAAI,CAAC;AAC5D;AASgB,SAAAC,EACdF,GACAJ,GACAO,GACc;AACV,MAAAJ,EAAUC,GAAOJ,CAAK;AACjB,WAAA;AAGT,QAAM,IAAI,UAAUQ,EAAYR,GAAOO,CAA2E,CAAC;AACrH;AAKO,SAASE,EAAST,GAAiC;AACxD,SAAO,OAAOA,KAAU;AAC1B;AAKgB,SAAAU,EAAaV,GAAgBO,GAAwC;AAC/E,MAAAE,EAAST,CAAK;AACT,WAAA;AAGT,QAAM,IAAI,UAAUQ,EAAYR,GAAOO,KAAgB,4CAA4C,CAAC;AACtG;AAOO,SAASI,EAAgDX,GAA4B;AACnF,SAAAD,EAAOC,CAAK,MAAM;AAC3B;AA4EO,SAASY,KAAwCC,GAAiB;AACjE,QAAAC,IAAcD,EAAK,CAAC,GACpBN,IAAeE,EAASI,EAAK,CAAC,CAAC,IACjCA,EAAK,CAAC,IACN,wBAAwBC,EAAY,IAAI,6BAEtCC,IAAO,CAACf,MAA+B;AAC3C,QAAIA,aAAiBc;AACZ,aAAA;AAGT,UAAM,IAAI,UAAUN,EAAYR,GAAOO,CAAY,CAAC;AAAA,EACtD;AAEI,SAAAM,EAAK,SAAS,IACTE,IAEAA,EAAKF,EAAK,CAAC,CAAC;AAEvB;AAKO,SAASG,EAAShB,GAAoE;AAC3F,SAAOA,KAAS,QAAQ,OAAOA,KAAU,YAAY,CAACE,EAAQF,CAAK;AACrE;AAKgB,SAAAiB,EAAajB,GAAgBO,GAAwC;AAC/E,MAAAS,EAAShB,CAAK;AACT,WAAA;AAGT,QAAM,IAAI,UAAUQ,EAAYR,GAAOO,CAA6D,CAAC;AACvG;AAKA,SAASC,EAAYR,GAAgBkB,GAAiB;AApO/C,MAAAC;AAqOC,QAAAC,IAAWrB,EAAOC,CAAK,GAGvBqB,MAAcF,IAAAnB,KAAA,gBAAAA,EAAO,aAAP,gBAAAmB,EAAA,KAAAnB,OAAuB,OAAOA,CAAK;AAEvD,SAAOkB,EAAQ,WAAW,MAAME,CAAQ,EAAE,WAAW,MAAMC,CAAW;AACxE;"}
@@ -1,8 +1,8 @@
1
- type TypeNames = "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "null" | "array" | "class" | "promise" | "NaN";
1
+ type TypeNames = "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "null" | "array" | "class" | "promise" | "map" | "set" | "NaN";
2
2
  /**
3
3
  * Extends `typeof` operator with more specific and useful type distinctions.
4
4
  */
5
- export declare function typeOf(value: unknown): TypeNames;
5
+ export declare function typeOf(value: any): TypeNames;
6
6
  /**
7
7
  * Throws a TypeError unless `condition` is truthy.
8
8
  *
@@ -18,12 +18,6 @@ export declare function isArray(value: unknown): value is Array<unknown>;
18
18
  * Throws an error if `value` is not an array.
19
19
  */
20
20
  export declare function assertArray(value: unknown, errorMessage?: string): value is Array<unknown>;
21
- /**
22
- * Returns a function that takes a `value` and ensures that it is an array for which `check` returns true for every item.
23
- *
24
- * @param check - Function to check items against.
25
- */
26
- export declare function isArrayOf<T>(check: (item: unknown) => boolean): (value: unknown) => value is T[];
27
21
  /**
28
22
  * Returns true when `value` is an array and `check` returns true for every item.
29
23
  *
@@ -31,12 +25,6 @@ export declare function isArrayOf<T>(check: (item: unknown) => boolean): (value:
31
25
  * @param value - A possible array.
32
26
  */
33
27
  export declare function isArrayOf<T>(check: (item: unknown) => boolean, value: unknown): value is T[];
34
- /**
35
- * Returns a function that takes a `value` and throws a TypeError unless it is an array for which `check` returns true for every item.
36
- *
37
- * @param check - Function to check items against.
38
- */
39
- export declare function assertArrayOf<T>(check: (item: unknown) => boolean): (value: unknown) => value is T[];
40
28
  /**
41
29
  * Throws a TypeError unless `value` is an array and `check` returns true for every item.
42
30
  *
@@ -45,14 +33,6 @@ export declare function assertArrayOf<T>(check: (item: unknown) => boolean): (va
45
33
  * @param errorMessage - A custom error message.
46
34
  */
47
35
  export declare function assertArrayOf<T>(check: (item: unknown) => boolean, value: unknown, errorMessage?: string): value is T[];
48
- /**
49
- * Returns true if `value` is equal to `true` or `false`.
50
- */
51
- export declare function isBoolean(value: unknown): value is boolean;
52
- /**
53
- * Throws a TypeError unless `value` is equal to `true` or `false`.
54
- */
55
- export declare function assertBoolean(value: unknown, errorMessage?: string): value is boolean;
56
36
  /**
57
37
  * Returns true if `value` is a string.
58
38
  */
@@ -77,34 +57,6 @@ export declare function isNumber(value: unknown): value is number;
77
57
  * Throws a TypeError unless `value` is a number.
78
58
  */
79
59
  export declare function assertNumber(value: unknown, errorMessage?: string): value is number;
80
- /**
81
- * Returns true if `value` implements the Promise protocol.
82
- * This matches true instances of Promise as well as any object that
83
- * implements `next`, `catch` and `finally` methods.
84
- *
85
- * To strictly match instances of Promise, use `isInstanceOf(Promise)`.
86
- */
87
- export declare function isPromise<T = unknown>(value: unknown): value is Promise<T>;
88
- /**
89
- * Throws a TypeError unless `value` implements the Promise protocol.
90
- * This matches true instances of Promise as well as any object that
91
- * implements `next`, `catch` and `finally` methods.
92
- *
93
- * To strictly allow only instances of Promise, use `Type.assertInstanceOf(Promise)`.
94
- */
95
- export declare function assertPromise<T = unknown>(value: unknown, errorMessage?: string): value is Promise<T>;
96
- /**
97
- * Returns true if `value` is a class.
98
- */
99
- export declare function isClass(value: unknown): value is {
100
- new (): unknown;
101
- };
102
- /**
103
- * Throws a TypeError unless `value` is a class.
104
- */
105
- export declare function assertClass(value: unknown, errorMessage?: string): value is {
106
- new (): unknown;
107
- };
108
60
  /**
109
61
  * Returns a function that takes a `value` and returns true if `value` is an instance of `constructor`.
110
62
  *
@@ -132,30 +84,6 @@ export declare function assertInstanceOf<T extends Function>(constructor: T): (v
132
84
  * @param errorMessage - A custom error message for when the assertion fails.
133
85
  */
134
86
  export declare function assertInstanceOf<T extends Function>(constructor: T, value: unknown, errorMessage?: string): value is T;
135
- /**
136
- * Returns true if `value` is a Map.
137
- */
138
- export declare function isMap<K = unknown, V = unknown>(value: any): value is Map<K, V>;
139
- /**
140
- * Throws a TypeError unless `value` is a Map.
141
- */
142
- export declare function assertMap<K = unknown, V = unknown>(value: any, errorMessage?: string): value is Map<K, V>;
143
- /**
144
- * Returns true if `value` is a Set.
145
- */
146
- export declare function isSet<T = unknown>(value: any): value is Set<T>;
147
- /**
148
- * Throws a TypeError if `value` is not a Set.
149
- */
150
- export declare function assertSet<T = unknown>(value: any, errorMessage?: string): value is Set<T>;
151
- /**
152
- * Returns true if `value` implements the Iterable protocol.
153
- */
154
- export declare function isIterable<T>(value: any): value is Iterable<T>;
155
- /**
156
- * Throws a TypeError unless `value` implements the Iterable protocol.
157
- */
158
- export declare function assertIterable<T>(value: any, errorMessage?: string): value is Iterable<T>;
159
87
  /**
160
88
  * Returns true if `value` is a plain JavaScript object.
161
89
  */
@@ -164,28 +92,4 @@ export declare function isObject(value: unknown): value is Record<string | numbe
164
92
  * Throws a TypeError unless `value` is a plain JavaScript object.
165
93
  */
166
94
  export declare function assertObject(value: unknown, errorMessage?: string): value is object;
167
- /**
168
- * Returns true if `value` is equal to `null`.
169
- */
170
- export declare function isNull(value: unknown): value is null;
171
- /**
172
- * Throws a TypeError unless `value` is equal to `null`.
173
- */
174
- export declare function assertNull(value: unknown, errorMessage?: string): value is null;
175
- /**
176
- * Returns true if `value` is equal to `undefined`.
177
- */
178
- export declare function isUndefined(value: unknown): value is undefined;
179
- /**
180
- * Throws a TypeError unless `value` is equal to `undefined`.
181
- */
182
- export declare function assertUndefined(value: unknown, errorMessage?: string): value is undefined;
183
- /**
184
- * Returns true if `value` is equal to `null` or `undefined`.
185
- */
186
- export declare function isEmpty(value: unknown): value is void;
187
- /**
188
- * Throws a TypeError unless `value` is equal to `null` or `undefined`.
189
- */
190
- export declare function assertEmpty(value: unknown, errorMessage?: string): value is void;
191
95
  export {};
@@ -0,0 +1 @@
1
+ export {};
package/dist/types.d.ts CHANGED
@@ -1,17 +1,31 @@
1
1
  import type * as CSS from "csstype";
2
- import { Ref, type Markup } from "./markup.js";
3
- import { SettableState, State } from "./state.js";
2
+ import type { Markup, MarkupNode } from "./core/markup.js";
3
+ import type { Signal } from "./core/signals.js";
4
+ import type { Context } from "./core/context.js";
5
+ export type Env = "production" | "development";
4
6
  /**
5
7
  * Represents everything that can be handled as a DOM node.
6
8
  * These are all the items considered valid to pass as children to any element.
7
9
  */
8
- export type Renderable = string | number | Markup | false | null | undefined | State<any> | (string | number | Markup | false | null | undefined | State<any>)[];
9
- export type Stringable = {
10
- toString(): string;
11
- };
12
- type MaybeState<T> = T | State<T> | State<T | undefined>;
13
- type OptionalProperty<T> = T | State<T> | State<T | undefined>;
14
- type RequiredProperty<T> = T | State<T>;
10
+ export type Renderable = string | number | Node | Markup | MarkupNode | false | null | undefined | Signal<any> | (string | number | Node | Markup | MarkupNode | false | null | undefined | Signal<any>)[];
11
+ export interface BaseProps {
12
+ children?: Renderable;
13
+ }
14
+ /**
15
+ *
16
+ */
17
+ export type View<P> = (this: Context, props: P, context: Context) => Renderable;
18
+ /**
19
+ *
20
+ */
21
+ export type Store<Options, Value> = (this: Context, options: Options, context: Context) => Value;
22
+ /**
23
+ *
24
+ */
25
+ export type Mixin<E extends Element = Element> = (element: E, context: Context) => void;
26
+ type MaybeSignal<T> = T | Signal<T> | Signal<T | undefined>;
27
+ type OptionalProperty<T> = MaybeSignal<T>;
28
+ type RequiredProperty<T> = T | Signal<T>;
15
29
  type AutocapitalizeValues = "off" | "on" | "none" | "sentences" | "words" | "characters";
16
30
  type ContentEditableValues = true | false | "true" | "false" | "plaintext-only" | "inherit";
17
31
  type ClassListValues = string | ClassMap | Array<string | ClassMap | (string | ClassMap)[]>;
@@ -23,21 +37,31 @@ type InputModeValues = "decimal" | "email" | "none" | "numeric" | "search" | "te
23
37
  * Properties common to all Elements.
24
38
  */
25
39
  export interface ElementProps {
40
+ /**
41
+ * Sets the value as an HTML attribute.
42
+ */
43
+ [key: `attr:${string}`]: OptionalProperty<any>;
44
+ /**
45
+ * Sets the value directly on the HTMLElement as a property.
46
+ */
47
+ [key: `prop:${string}`]: OptionalProperty<any>;
48
+ /**
49
+ * Attaches an event listener to the element (with `addEventListener`).
50
+ */
51
+ [key: `on:${string}`]: OptionalProperty<EventHandler<Event>>;
26
52
  /**
27
53
  * HTML attributes to assign to the element.
28
54
  */
29
- attributes?: OptionalProperty<Record<string, any>>;
30
55
  /**
31
56
  * Object of event listeners.
32
57
  */
33
- eventListeners?: OptionalProperty<Record<string, EventHandler<Event>>>;
34
58
  /**
35
59
  * CSS classes to be applied to this element. In addition to the standard space-separated list of class names,
36
60
  * this property also supports a class map object with class names as keys and booleans as values.
37
61
  * Class names in a class map will be applied to the element while their values are true. Also supports an
38
62
  * array of strings and class maps.
39
63
  *
40
- * Alias of `className`.
64
+ * @alias className
41
65
  *
42
66
  * @example
43
67
  * <div class="one-class" />
@@ -57,6 +81,8 @@ export interface ElementProps {
57
81
  * Class names in a class map will be applied to the element while their values are true. Also supports an
58
82
  * array of strings and class maps.
59
83
  *
84
+ * @alias class
85
+ *
60
86
  * @example
61
87
  * <div className="one-class" />
62
88
  *
@@ -71,22 +97,39 @@ export interface ElementProps {
71
97
  className?: OptionalProperty<ClassListValues>;
72
98
  /**
73
99
  * A unique string to identify this element.
100
+ *
101
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/id
74
102
  */
75
103
  id?: OptionalProperty<string>;
104
+ /**
105
+ * Renders a string of HTML as the children of this element.
106
+ * Equivalent to setting `innerHTML` on a DOM element.
107
+ *
108
+ * `NOTE` This property does no sanitization. If it's in the string, it's in the DOM. Be mindful when handling user-generated content.
109
+ */
110
+ innerHTML?: OptionalProperty<string>;
111
+ /**
112
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/popover
113
+ */
114
+ popover?: OptionalProperty<"auto" | "hint" | "manual" | true | false>;
115
+ /**
116
+ * Specifies the element's [WAI-ARIA role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles).
117
+ *
118
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/role
119
+ */
120
+ role?: OptionalProperty<string>;
76
121
  /**
77
122
  * Scroll position from the left (on the X axis), if this element is scrollable.
123
+ *
124
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
78
125
  */
79
126
  scrollLeft?: OptionalProperty<number>;
80
127
  /**
81
128
  * Scroll position from the top (on the Y axis) if this element is scrollable.
82
- */
83
- scrollTop?: OptionalProperty<number>;
84
- /**
85
- * Enables or disables checking for spelling errors in an element's content.
86
129
  *
87
- * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/spellcheck
130
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop
88
131
  */
89
- spellcheck?: OptionalProperty<boolean>;
132
+ scrollTop?: OptionalProperty<number>;
90
133
  /**
91
134
  * Specifies whether an element's content should be translated when the page is localized.
92
135
  *
@@ -105,12 +148,18 @@ export interface ElementProps {
105
148
  * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/slot
106
149
  */
107
150
  slot?: OptionalProperty<string>;
151
+ /**
152
+ * Enables or disables checking for spelling errors in an element's content.
153
+ *
154
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/spellcheck
155
+ */
156
+ spellCheck?: OptionalProperty<boolean>;
108
157
  /**
109
158
  * Inline styles applied to the element. Can be passed as a string or as an object.
110
159
  *
111
160
  * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/style
112
161
  */
113
- style?: string | CSSProperties | State<string> | State<CSSProperties> | State<string | CSSProperties> | State<string | undefined> | State<CSSProperties | undefined> | State<string | CSSProperties | undefined>;
162
+ style?: string | CSSProperties | Signal<string> | Signal<CSSProperties> | Signal<string | CSSProperties> | Signal<string | undefined> | Signal<CSSProperties | undefined> | Signal<string | CSSProperties | undefined>;
114
163
  /**
115
164
  * Fired when a CSS animation unexpectedly aborts.
116
165
  *
@@ -178,6 +227,12 @@ export interface ElementProps {
178
227
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionupdate_event
179
228
  */
180
229
  onCompositionUpdate?: OptionalProperty<EventHandler<CompositionEvent>>;
230
+ /**
231
+ * Fired when the user attempts to open a context menu. Typically triggered by clicking the right mouse button.
232
+ *
233
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event
234
+ */
235
+ onContextMenu?: OptionalProperty<EventHandler<PointerEvent>>;
181
236
  /**
182
237
  * Fired when a pointing device button is rapidly clicked twice while the pointer is inside the element.
183
238
  *
@@ -452,6 +507,12 @@ export interface ElementProps {
452
507
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionupdate_event
453
508
  */
454
509
  oncompositionupdate?: OptionalProperty<EventHandler<CompositionEvent>>;
510
+ /**
511
+ * Fired when the user attempts to open a context menu. Typically triggered by clicking the right mouse button.
512
+ *
513
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event
514
+ */
515
+ oncontextmenu?: OptionalProperty<EventHandler<PointerEvent>>;
455
516
  /**
456
517
  * Fired when a pointing device button is rapidly clicked twice while the pointer is inside the element.
457
518
  *
@@ -683,6 +744,12 @@ export interface HTMLElementProps extends ElementProps {
683
744
  * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/contentEditable
684
745
  */
685
746
  contentEditable?: OptionalProperty<ContentEditableValues>;
747
+ /**
748
+ * Stores values on the element as attributes prefixed with `data-`.
749
+ *
750
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset
751
+ */
752
+ dataset?: OptionalProperty<Record<string, string>>;
686
753
  /**
687
754
  * Specifies text directionality of the content of this element. Some languages, such as Arabic, are written from right to left (specified here as "rtl").
688
755
  *
@@ -729,7 +796,6 @@ export interface HTMLElementProps extends ElementProps {
729
796
  /**
730
797
  * TODO: Add support. Currently experimental.
731
798
  */
732
- role?: OptionalProperty<string>;
733
799
  /**
734
800
  * This element's position in the tab order, or the order this element will be focused as the user cycles through elements with the tab key.
735
801
  *
@@ -938,6 +1004,10 @@ export interface HTMLElementProps extends ElementProps {
938
1004
  onpaste?: OptionalProperty<EventHandler<ClipboardEvent>>;
939
1005
  }
940
1006
  export interface SVGElementProps extends ElementProps {
1007
+ /**
1008
+ * A mixin function or an array of mixin functions to be applied to this element.
1009
+ */
1010
+ mixin?: Mixin<SVGElement> | Mixin<SVGElement>[];
941
1011
  }
942
1012
  /**
943
1013
  * Mapping of event props to event names.
@@ -1210,7 +1280,7 @@ export type CSSProperties = {
1210
1280
  [K in keyof Styles]: OptionalProperty<Styles[K]>;
1211
1281
  };
1212
1282
  export interface ClassMap {
1213
- [className: string]: MaybeState<any>;
1283
+ [className: string]: MaybeSignal<any>;
1214
1284
  }
1215
1285
  export type EventHandler<E> = (event: E) => void;
1216
1286
  export interface PropertiesOf<E extends HTMLElement> extends HTMLElementProps {
@@ -1221,7 +1291,11 @@ export interface PropertiesOf<E extends HTMLElement> extends HTMLElementProps {
1221
1291
  /**
1222
1292
  * Receives a reference to the DOM node when rendered.
1223
1293
  */
1224
- ref?: Ref<E> | Ref<HTMLElement> | Ref<Element> | Ref<Node>;
1294
+ ref?: ((value: E | undefined) => void) | ((value: HTMLElement | undefined) => void) | ((value: Element | undefined) => void) | ((value: Node | undefined) => void);
1295
+ /**
1296
+ * A mixin function or an array of mixin functions to be applied to this element.
1297
+ */
1298
+ mixin?: Mixin<E> | Mixin<E>[];
1225
1299
  }
1226
1300
  /**
1227
1301
  * The following elements are defined based on the WHATWG HTML spec:
@@ -2098,7 +2172,7 @@ interface HTMLMediaElementProps<T extends HTMLMediaElement> extends HTMLElementP
2098
2172
  *
2099
2173
  * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/srcObject
2100
2174
  */
2101
- srcObject?: MediaStream | MediaSource | Blob | File | State<MediaStream> | State<MediaStream | undefined> | State<MediaSource> | State<MediaSource | undefined> | State<Blob> | State<Blob | undefined> | State<File> | State<File | undefined>;
2175
+ srcObject?: MediaStream | MediaSource | Blob | File | Signal<MediaStream> | Signal<MediaStream | undefined> | Signal<MediaSource> | Signal<MediaSource | undefined> | Signal<Blob> | Signal<Blob | undefined> | Signal<File> | Signal<File | undefined>;
2102
2176
  /**
2103
2177
  * The current audio volume of the media element. Must be a number between 0 and 1.
2104
2178
  *
@@ -2597,7 +2671,7 @@ interface HTMLImageElementProps extends PropertiesOf<HTMLImageElement> {
2597
2671
  *
2598
2672
  * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/sizes
2599
2673
  */
2600
- sizes?: MaybeState<string>;
2674
+ sizes?: MaybeSignal<string>;
2601
2675
  /**
2602
2676
  * The image URL.
2603
2677
  *
@@ -3143,7 +3217,6 @@ interface HTMLInputElementProps extends PropertiesOf<HTMLInputElement> {
3143
3217
  step?: OptionalProperty<number>;
3144
3218
  type?: OptionalProperty<InputType>;
3145
3219
  value?: OptionalProperty<string>;
3146
- $$value?: SettableState<any>;
3147
3220
  width?: OptionalProperty<string | number> | OptionalProperty<string> | OptionalProperty<number>;
3148
3221
  title?: OptionalProperty<string>;
3149
3222
  /**
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,18 @@
1
1
  export declare const noOp: () => void;
2
- export declare function deepEqual(one: any, two: any): boolean;
2
+ export declare function getUniqueId(): string;
3
+ /**
4
+ * Equality check that passes if both values are the same object.
5
+ * This is the default equality check for states.
6
+ */
7
+ export declare function strictEqual(a: any, b: any): boolean;
8
+ /**
9
+ * Equality check that passes if both values are the same object, or if both are objects or arrays with equal keys and values.
10
+ */
11
+ export declare function shallowEqual(a: any, b: any): boolean;
12
+ /**
13
+ * Equality check that passes if two objects have equal values, even if they are not the same object.
14
+ */
15
+ export declare function deepEqual(a: any, b: any): boolean;
3
16
  /**
4
17
  * Takes an old value and a new value. Returns a merged copy if both are objects, otherwise returns the new value.
5
18
  */
@@ -13,8 +26,12 @@ export declare function merge(one: unknown, two: unknown): any;
13
26
  * @param object - An object to clone without the omitted keys.
14
27
  */
15
28
  export declare function omit<O extends Record<any, any>>(keys: (keyof O)[], object: O): Record<any, any>;
16
- export declare function getDefaultConsole(): any;
17
- export declare function colorFromString(value: string): string;
29
+ export declare function toArray<T>(value: T | T[]): T[];
30
+ export declare function toCamelCase(s: string): string;
31
+ /**
32
+ * Takes any string and returns an OKLCH color.
33
+ */
34
+ export declare function okhash(value: string): string;
18
35
  export type MatcherFunction = (value: string) => boolean;
19
36
  /**
20
37
  * Parses a filter string into a matcher function.
package/docs/http.md ADDED
@@ -0,0 +1,29 @@
1
+ # HTTP Client
2
+
3
+ > TODO: Write me.
4
+
5
+ This page goes into detail on how to use the built in HTTP client.
6
+
7
+ ```js
8
+ import { http } from "@manyducks.co/dolla";
9
+
10
+ http.use(async (req, next) => {
11
+ // Apply auth header to all API routes.
12
+ if (req.url.pathname.startsWith("/api/")) {
13
+ req.headers.set("authorization", `Bearer ${localStorage.getItem("api-key")}`);
14
+ }
15
+
16
+ await next();
17
+ });
18
+
19
+ const res = await http.get("/api/some-api-route");
20
+ res.body; // body is already parsed as JSON if server responded with JSON
21
+ ```
22
+
23
+ ---
24
+
25
+ End.
26
+
27
+ - [🗂️ Docs](./index.md)
28
+ - [🏠 README](../README.md)
29
+ - [🦆 That's a lot of ducks.](https://www.manyducks.co)
package/docs/i18n.md ADDED
@@ -0,0 +1,43 @@
1
+ # Internationalization (i18n) Support
2
+
3
+ ```jsx
4
+ import { $, mount } from "@manyducks.co/dolla";
5
+ import { i18n, t } from "@manyducks.co/dolla/i18n";
6
+
7
+
8
+ function CounterView(props) {
9
+ const $count = $(0);
10
+
11
+ const increment = () => {
12
+ $count(count => count + 1);
13
+ };
14
+
15
+ return (
16
+ <div>
17
+ <p>Clicks: {$count}</p>
18
+ <button onClick={increment}>{t("buttonLabel")}</button>
19
+ </div>
20
+ );
21
+ });
22
+
23
+ // Await i18n setup before mounting the app to make sure translations are loaded.
24
+ i18n
25
+ .setup({
26
+ locale: "en",
27
+ translations: [
28
+ { locale: "en", strings: { buttonLabel: "Click here to increment" } },
29
+ { locale: "ja", strings: { buttonLabel: "ここに押して増加する" } },
30
+ ],
31
+ })
32
+ .then(() => {
33
+ return mount(document.body, CounterView);
34
+ });
35
+ ```
36
+
37
+ ---
38
+
39
+ End.
40
+
41
+ - [🗂️ Docs](./index.md)
42
+ - [🏠 README](../README.md)
43
+ - [🦆 That's a lot of ducks.](https://www.manyducks.co)
package/docs/index.md ADDED
@@ -0,0 +1,10 @@
1
+ # Dolla Docs
2
+
3
+ > Write table of contents (see files in this folder in the meantime)
4
+
5
+ ---
6
+
7
+ End.
8
+
9
+ - [🏠 README](../README.md)
10
+ - [🦆 That's a lot of ducks.](https://www.manyducks.co)
package/docs/markup.md ADDED
@@ -0,0 +1,16 @@
1
+ # Markup
2
+
3
+ Dolla creates a tree of views that manage the DOM, updating attributes and recreating parts of the DOM as signal values change.
4
+
5
+ ```js
6
+ import { $, m, render } from "@manyducks.co/dolla";
7
+
8
+ const $count = $(0);
9
+ const labelMarkup = m("span", { children: $count });
10
+ // or in JSX:
11
+ const labelMarkup = <span>{$count}</span>;
12
+
13
+ const rendered = render(labelMarkup);
14
+
15
+ rendered.mount(document.body);
16
+ ```
package/docs/mixins.md ADDED
@@ -0,0 +1,32 @@
1
+ # Mixins
2
+
3
+ Mixins are a way to add custom lifecycle handlers to plain DOM nodes without creating an entire view. You can encapsulate reusable logic in mixin functions and apply them like CSS classes.
4
+
5
+ Mixin functions take a reference to the element and a `MixinContext` object which adds lifecycle hooks similar to those of `ViewContext`.
6
+
7
+ ```tsx
8
+ import { type Mixin } from "@manyducks.co/dolla";
9
+
10
+ const logMe: Mixin = (element, ctx) => {
11
+ ctx.onMount(() => {
12
+ ctx.log("element mounted");
13
+ });
14
+ ctx.onUnmount(() => {
15
+ ctx.log("element unmounted");
16
+ });
17
+ };
18
+
19
+ // Pass one mixin
20
+ <h1 mixin={logMe}>Title</h1>;
21
+
22
+ // Or an array of mixins
23
+ <p mixin={[logMe, anotherMixin, yetAnotherMixin]}>Text goes here...</p>;
24
+ ```
25
+
26
+ ---
27
+
28
+ End.
29
+
30
+ - [🗂️ Docs](./index.md)
31
+ - [🏠 README](../README.md)
32
+ - [🦆 That's a lot of ducks.](https://www.manyducks.co)