@manyducks.co/dolla 1.0.1 → 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +47 -23
  2. package/build.js +5 -5
  3. package/dist/fragment-s33qZBzz.js +1241 -0
  4. package/dist/fragment-s33qZBzz.js.map +1 -0
  5. package/dist/index.d.ts +42 -0
  6. package/dist/index.js +1308 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/jsx-dev-runtime.d.ts +2 -0
  9. package/dist/jsx-dev-runtime.js +17 -0
  10. package/dist/jsx-dev-runtime.js.map +1 -0
  11. package/{lib/jsx → dist}/jsx-runtime.d.ts +3 -4
  12. package/dist/jsx-runtime.js +20 -0
  13. package/dist/jsx-runtime.js.map +1 -0
  14. package/{lib → dist}/markup.d.ts +12 -13
  15. package/dist/modules/dolla.d.ts +87 -0
  16. package/dist/modules/http.d.ts +57 -0
  17. package/dist/modules/language.d.ts +41 -0
  18. package/{lib/stores → dist/modules}/render.d.ts +5 -6
  19. package/{lib/stores → dist/modules}/router.d.ts +37 -39
  20. package/{lib → dist}/nodes/cond.d.ts +1 -4
  21. package/{lib → dist}/nodes/html.d.ts +2 -5
  22. package/{lib → dist}/nodes/observer.d.ts +2 -5
  23. package/{lib → dist}/nodes/outlet.d.ts +1 -4
  24. package/{lib → dist}/nodes/portal.d.ts +1 -3
  25. package/{lib → dist}/nodes/repeat.d.ts +2 -5
  26. package/{lib → dist}/nodes/text.d.ts +1 -1
  27. package/{lib → dist}/signals.d.ts +37 -54
  28. package/{lib → dist}/types.d.ts +0 -8
  29. package/{lib → dist}/utils.d.ts +10 -0
  30. package/dist/view.d.ts +44 -0
  31. package/dist/views/default-crash-page.d.ts +8 -0
  32. package/notes/scratch.md +120 -0
  33. package/package.json +11 -12
  34. package/vite.config.js +27 -0
  35. package/lib/app.d.ts +0 -83
  36. package/lib/classes/CrashCollector.d.ts +0 -30
  37. package/lib/classes/DebugHub.d.ts +0 -61
  38. package/lib/classes/EventEmitter.d.ts +0 -44
  39. package/lib/index.d.ts +0 -21
  40. package/lib/index.js +0 -4176
  41. package/lib/index.js.map +0 -7
  42. package/lib/jsx/jsx-dev-runtime.d.ts +0 -3
  43. package/lib/jsx/jsx-dev-runtime.js +0 -20
  44. package/lib/jsx/jsx-dev-runtime.js.map +0 -7
  45. package/lib/jsx/jsx-runtime.js +0 -22
  46. package/lib/jsx/jsx-runtime.js.map +0 -7
  47. package/lib/signals.test.d.ts +0 -1
  48. package/lib/spring.d.ts +0 -0
  49. package/lib/state.d.ts +0 -103
  50. package/lib/store.d.ts +0 -59
  51. package/lib/stores/dialog.d.ts +0 -32
  52. package/lib/stores/document.d.ts +0 -11
  53. package/lib/stores/http.d.ts +0 -60
  54. package/lib/stores/language.d.ts +0 -36
  55. package/lib/testing/classes/MockHTTP.d.ts +0 -10
  56. package/lib/testing/index.d.ts +0 -4
  57. package/lib/testing/makeMockDOMNode.d.ts +0 -10
  58. package/lib/testing/makeMockFetch._test.d.ts +0 -1
  59. package/lib/testing/makeMockFetch.d.ts +0 -36
  60. package/lib/testing/makeMockFetch.test.d.ts +0 -1
  61. package/lib/testing/makeMockFetch.test_skip.d.ts +0 -1
  62. package/lib/testing/stores/dialog.d.ts +0 -6
  63. package/lib/testing/stores/http.d.ts +0 -13
  64. package/lib/testing/stores/page.d.ts +0 -7
  65. package/lib/testing/stores/router.d.ts +0 -12
  66. package/lib/testing/wrapStore._test.d.ts +0 -1
  67. package/lib/testing/wrapStore.d.ts +0 -8
  68. package/lib/testing/wrapStore.test.d.ts +0 -1
  69. package/lib/testing/wrapStore.test_skip.d.ts +0 -1
  70. package/lib/testing/wrapView.d.ts +0 -0
  71. package/lib/view.d.ts +0 -88
  72. package/lib/views/default-crash-page.d.ts +0 -7
  73. package/lib/views/store-scope.d.ts +0 -13
  74. /package/{lib → dist}/routing.d.ts +0 -0
  75. /package/{lib → dist}/routing.test.d.ts +0 -0
  76. /package/{lib → dist}/typeChecking.d.ts +0 -0
  77. /package/{lib → dist}/views/default-view.d.ts +0 -0
  78. /package/{lib → dist}/views/fragment.d.ts +0 -0
package/notes/scratch.md CHANGED
@@ -1,5 +1,125 @@
1
1
  # Scratch Note
2
2
 
3
+ What if Dolla was just a global object that you don't instantiate. I have never personally run into a use case for having more than one app on a page at once. In all my projects, the page and the app are synonymous.
4
+
5
+ Doing this would make it possible to access things inside the Dolla app from _outside_ code such as Quill blots. Effectively all code that has access to your Dolla import is _inside_ the app.
6
+
7
+ - Remove stores in favor of just exporting variables and functions from ES modules and importing them where desired.
8
+ -
9
+
10
+ ```jsx
11
+ import Dolla from "@manyducks.co/dolla";
12
+
13
+ // Languages: add translation, set language and get localized string as a signal
14
+ Dolla.language.setup({
15
+ initialLanguage: Dolla.language.detect({ fallback: "ja" }), // Detect user's language and fall back to passed value
16
+ languages: [
17
+ { name: "ja", path: "/static/locales/ja.json" },
18
+ {
19
+ name: "en",
20
+ fetch: async () => {
21
+ // Pass a path string, or if additional logic is needed, a fetch function.
22
+ const res = await Dolla.http.get("/static/locales/en.json");
23
+ return res.body;
24
+ }
25
+ }
26
+ ]
27
+ });
28
+
29
+ Dolla.language.$current
30
+ Dolla.language.t$()
31
+
32
+ // A single setup call to keep things contained (must happen before mount)
33
+ Dolla.router.setup({
34
+ // Initial path must point to a route that actually exists (will be validated on mount) (initialPath is "/" by default)
35
+ initialPath: "/",
36
+ routes: [
37
+ { path: "/", view: SomeView }
38
+ ]
39
+ });
40
+ // And then you can route from anywhere.
41
+ Dolla.router.go("/some/path");
42
+ // Or get route information from anywhere.
43
+ Dolla.router.$path;
44
+ Dolla.router.$params;
45
+
46
+ // Also utils are available
47
+ const joinedPath = Dolla.router.utils.joinPath("/api/records", "5");
48
+ const resolvedPath = Dolla.router.utils.resolvePath("../"); // Resolves with window.location.href as the base
49
+
50
+ // Initializes the app and matches first route
51
+ Dolla.mount("#app");
52
+ // If you pass a view as the second argument it becomes the root view (this works for simple apps without a router)
53
+ Dolla.mount("#app", MyRootView);
54
+ // If router setup function wasn't called then the root view is mounted equivalent to the following:
55
+ Dolla.router.setup({
56
+ defaultPath: "/",
57
+ routes: [
58
+ { path: "/*", view: MyRootView },
59
+ ]
60
+ });
61
+
62
+ // Add HTTP middleware
63
+ Dolla.http.use(async (req, next) => {
64
+ const res = await next()
65
+ });
66
+ // Make HTTP calls
67
+ const res = await Dolla.get("/some/path");
68
+
69
+ // Adjust log level
70
+ Dolla.setLogLevel(Dolla.LOG_LEVEL_INFO);
71
+ Dolla.setLogFilter("*,-Dolla/*")
72
+ // Create a scoped logger
73
+ const debug = Dolla.createLogger("debug-logger");
74
+ debug.log("HELLO");
75
+ debug.warn("THIS IS A SCOPED LOGGER");
76
+
77
+ // Efficiently and safely read and mutate the DOM using Dolla's render batching
78
+ Dolla.render.read(() => {
79
+ // Reference DOM nodes
80
+ });
81
+ Dolla.render.update(() => {
82
+ // Mutate the DOM as part of Dolla's next batch
83
+ }, "some-key");
84
+
85
+ // Respond to lifecycle events
86
+ Dolla.onMount(() => {});
87
+ Dolla.onRouteMatch(() => {});
88
+ // Dolla.onWhatever(() => {});
89
+
90
+ interface SomeViewProps {}
91
+
92
+ function SomeView (props: SomeViewProps, ctx: Dolla.ViewContext) {
93
+ const debug = Dolla.createLogger("SomeView");
94
+
95
+ // returns a signal and a setter function
96
+ const [$someValue, setSomeValue] = Dolla.createSignal(4);
97
+
98
+ // Router is now a part of the Dolla object
99
+ Dolla.router.$path;
100
+ Dolla.router.$params;
101
+
102
+ Dolla.router.go("/some-other-path");
103
+
104
+ ctx.watch([$someValue], (value) => {
105
+ debug.log(value);
106
+ });
107
+
108
+ // View helpers are on ViewContext
109
+ ctx.repeat()
110
+ ctx.cond()
111
+ ctx.render([...states], (...values) => {
112
+ // return Renderable (equivalent to Dolla.derive(states, (...values) => Renderable))
113
+ })
114
+ ctx.portal()
115
+ ctx.outlet()
116
+
117
+ // TODO: Add Dolla.dialog.show() and Dolla.toast.show() or create separate libraries?
118
+
119
+ return <h1>{ctx.t$("home.headerText")}</h1>;
120
+ }
121
+ ```
122
+
3
123
  ```tsx
4
124
  // import { signal, computed } from "@manyducks.co/dolla";
5
125
 
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "@manyducks.co/dolla",
3
- "version": "1.0.1",
3
+ "version": "2.0.0-alpha.0",
4
4
  "description": "Front-end components, routing and state management.",
5
- "main": "lib/index.js",
6
- "types": "./index.d.ts",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
7
  "type": "module",
8
8
  "sideEffects": false,
9
9
  "repository": "https://github.com/manyducksco/dolla",
10
10
  "scripts": {
11
11
  "test": "npm run build && node --test",
12
- "build": "tsc && node build.js",
12
+ "build:esbuild": "tsc && node build.js",
13
+ "build": "vite build && tsc",
13
14
  "start": "tsc --watch",
14
15
  "prepublishOnly": "NODE_ENV=production npm run build"
15
16
  },
@@ -23,18 +24,15 @@
23
24
  "license": "MIT",
24
25
  "exports": {
25
26
  ".": {
26
- "import": "./lib/index.js",
27
+ "import": "./dist/index.js",
27
28
  "types": "./index.d.ts"
28
29
  },
29
- "./testing": {
30
- "import": "./lib/testing/index.js"
31
- },
32
30
  "./jsx-runtime": {
33
- "import": "./lib/jsx/jsx-runtime.js",
31
+ "import": "./dist/jsx-runtime.js",
34
32
  "types": "./jsx-runtime.d.ts"
35
33
  },
36
34
  "./jsx-dev-runtime": {
37
- "import": "./lib/jsx/jsx-dev-runtime.js",
35
+ "import": "./dist/jsx-dev-runtime.js",
38
36
  "types": "./jsx-dev-runtime.d.ts"
39
37
  }
40
38
  },
@@ -42,12 +40,13 @@
42
40
  "fetch-ponyfill": "^7.1.0",
43
41
  "history": "^5.3.0",
44
42
  "nanoid": "^5.0.4",
45
- "simple-color-hash": "^1.0.2"
43
+ "simple-color-hash": "^1.0.2",
44
+ "vite": "^6.0.7"
46
45
  },
47
46
  "devDependencies": {
48
47
  "@types/node": "^18.17.6",
49
48
  "csstype": "^3.1.3",
50
- "esbuild": "^0.20.0",
49
+ "esbuild": "^0.24.2",
51
50
  "prettier": "^3.2.4",
52
51
  "typescript": "^5.3.3",
53
52
  "zod": "^3.22.4"
package/vite.config.js ADDED
@@ -0,0 +1,27 @@
1
+ import { resolve } from "node:path";
2
+ import { defineConfig } from "vite";
3
+
4
+ export default defineConfig({
5
+ build: {
6
+ // minify: "terser",
7
+ // minify: false,
8
+ sourcemap: true,
9
+ lib: {
10
+ entry: {
11
+ index: resolve(__dirname, "src/index.ts"),
12
+ "jsx-runtime": resolve(__dirname, "src/jsx-runtime.js"),
13
+ "jsx-dev-runtime": resolve(__dirname, "src/jsx-dev-runtime.js"),
14
+ },
15
+ name: "Dolla",
16
+ formats: ["es"],
17
+ },
18
+ // rollupOptions: {
19
+ // external: ["vue"],
20
+ // output: {
21
+ // globals: {
22
+ // vue: "Vue",
23
+ // },
24
+ // },
25
+ // },
26
+ },
27
+ });
package/lib/app.d.ts DELETED
@@ -1,83 +0,0 @@
1
- import { CrashCollector } from "./classes/CrashCollector.js";
2
- import { DebugHub, type DebugOptions } from "./classes/DebugHub.js";
3
- import { DOMHandle } from "./markup.js";
4
- import { initStore, type Store } from "./store.js";
5
- import { type BuiltInStores } from "./types.js";
6
- import { type View } from "./view.js";
7
- interface StoreConfig<O, E> {
8
- store: Store<O, E>;
9
- options?: O;
10
- }
11
- interface IAppOptions {
12
- /**
13
- * Options for the debug system.
14
- */
15
- debug?: DebugOptions;
16
- /**
17
- * The view to be rendered by the app.
18
- */
19
- view?: View<{}>;
20
- /**
21
- * App-level stores.
22
- */
23
- stores?: StoreConfig<any, any>[];
24
- /**
25
- * Configures the app based on the environment it's running in.
26
- */
27
- mode?: "development" | "production";
28
- }
29
- export interface AppContext {
30
- crashCollector: CrashCollector;
31
- debugHub: DebugHub;
32
- stores: Map<keyof BuiltInStores | StoreRegistration["store"], StoreRegistration>;
33
- mode: "development" | "production";
34
- rootElement?: HTMLElement;
35
- rootView?: DOMHandle;
36
- }
37
- export interface ElementContext {
38
- stores: Map<StoreRegistration["store"], StoreRegistration>;
39
- isSVG?: boolean;
40
- componentName?: string;
41
- parent?: ElementContext;
42
- }
43
- /**
44
- * An object kept in App for each store registered with `addStore`.
45
- */
46
- export interface StoreRegistration<O = any> {
47
- store: Store<O, any>;
48
- options?: O;
49
- instance?: ReturnType<typeof initStore>;
50
- }
51
- interface ConfigureContext {
52
- /**
53
- * Returns the shared instance of `store`.
54
- */
55
- getStore<T extends Store<any, any>>(store: T): ReturnType<T>;
56
- /**
57
- * Returns the shared instance of a built-in store.
58
- */
59
- getStore<N extends keyof BuiltInStores>(name: N): BuiltInStores[N];
60
- }
61
- type ConfigureCallback = (ctx: ConfigureContext) => void | Promise<void>;
62
- export interface IApp {
63
- readonly isConnected: boolean;
64
- /**
65
- * Runs `callback` after app-level stores are connected to the app, but before views are connected to the DOM.
66
- * Use this function to run async configuration code before displaying content to the user.
67
- *
68
- * Note that this will delay content being displayed on the screen, so using some kind of splash screen is recommended.
69
- */
70
- configure(callback: ConfigureCallback): this;
71
- /**
72
- * Initializes and connects the app as a child of `element`.
73
- *
74
- * @param element - A selector string or a DOM node to attach to. If a string, follows the same format as that taken by `document.querySelector`.
75
- */
76
- connect(selector: string | Node): Promise<void>;
77
- /**
78
- * Disconnects views and tears down globals, removing the app from the page.
79
- */
80
- disconnect(): Promise<void>;
81
- }
82
- export declare function App(options?: IAppOptions): IApp;
83
- export {};
@@ -1,30 +0,0 @@
1
- interface ErrorContext {
2
- error: Error;
3
- severity: "error" | "crash";
4
- componentName: string;
5
- }
6
- interface CrashOptions {
7
- error: Error;
8
- componentName?: string;
9
- }
10
- type ErrorCallback = (ctx: ErrorContext) => void;
11
- /**
12
- * Receives errors that occur in components.
13
- */
14
- export declare class CrashCollector {
15
- #private;
16
- /**
17
- * Registers a callback to receive all errors that pass through the CrashCollector.
18
- * Returns a function that cancels this listener when called.
19
- */
20
- onError(callback: ErrorCallback): () => void;
21
- /**
22
- * Reports an unrecoverable error that requires crashing the whole app.
23
- */
24
- crash({ error, componentName }: CrashOptions): void;
25
- /**
26
- * Reports a recoverable error.
27
- */
28
- error({ error, componentName }: CrashOptions): void;
29
- }
30
- export {};
@@ -1,61 +0,0 @@
1
- import { type CrashCollector } from "./CrashCollector.js";
2
- export type DebugOptions = {
3
- /**
4
- * Determines which debug channels are printed. Supports multiple filters with commas,
5
- * a prepended `-` to exclude a channel and wildcards to match partial channels.
6
- *
7
- * @example "store:*,-store:test" // matches everything starting with "store" except "store:test"
8
- */
9
- filter?: string | RegExp;
10
- /**
11
- * Print info messages when true. Default: true for development builds, false for production builds.
12
- */
13
- info?: boolean | "development";
14
- /**
15
- * Print log messages when true. Default: true for development builds, false for production builds.
16
- */
17
- log?: boolean | "development";
18
- /**
19
- * Print warn messages when true. Default: true for development builds, false for production builds.
20
- */
21
- warn?: boolean | "development";
22
- /**
23
- * Print error messages when true. Default: true.
24
- */
25
- error?: boolean | "development";
26
- };
27
- type DebugHubOptions = DebugOptions & {
28
- crashCollector: CrashCollector;
29
- mode: "development" | "production";
30
- };
31
- export interface DebugChannelOptions {
32
- name: string;
33
- id?: string;
34
- }
35
- export interface DebugChannel {
36
- info(...args: any[]): void;
37
- log(...args: any[]): void;
38
- warn(...args: any[]): void;
39
- error(...args: any[]): void;
40
- }
41
- /**
42
- * The central trunk from which all channels branch.
43
- * Changing the filter here determines what kind of messages are printed across the app.
44
- */
45
- export declare class DebugHub {
46
- #private;
47
- constructor(options: DebugHubOptions, _console?: any);
48
- /**
49
- * Returns a debug channel labelled by `name`. Used for logging from components.
50
- */
51
- channel(options: DebugChannelOptions): DebugChannel;
52
- get filter(): string | RegExp;
53
- set filter(pattern: string | RegExp);
54
- }
55
- /**
56
- * Parses a filter string into a match function.
57
- *
58
- * @param pattern - A string or regular expression that specifies a pattern for names of debug channels you want to display.
59
- */
60
- export declare function makeMatcher(pattern: string | RegExp): (value: string) => boolean;
61
- export {};
@@ -1,44 +0,0 @@
1
- type EventListeners<E extends EventMap> = {
2
- [K in keyof E]?: EventCallback<E, K>[];
3
- };
4
- export type EventCallback<E extends EventMap, K extends keyof E> = (event: EmittedEvent<E, K>) => void;
5
- /**
6
- * A map of event names and data values that their listener callbacks take.
7
- */
8
- export interface EventMap {
9
- [name: string]: any;
10
- }
11
- /**
12
- * A hub for subscribing to and emitting events. A good pattern when you want to notify several parts of your app
13
- * at once when a condition changes in a central location. This is a similar pattern to Readable and Writable as far as
14
- * observability goes, but with the added ability to emit multiple event types each with their own separate listeners.
15
- */
16
- export declare class EventEmitter<E extends EventMap = EventMap> {
17
- listeners: EventListeners<E>;
18
- /**
19
- * Emit an event.
20
- */
21
- emit<K extends keyof E>(name: K, data: E[K]): void;
22
- /**
23
- * Listen for an event. The callback will be called whenever that event is emitted.
24
- * Returns a function that will cancel this listener when called.
25
- */
26
- on<K extends keyof EventListeners<E>>(name: K, callback: EventCallback<E, K>): () => void;
27
- /**
28
- * Listen for the next emitted event. The callback will be called once the next time that event is emitted,
29
- * and then never again. Returns a function that will cancel this listener when called.
30
- */
31
- once<K extends keyof EventListeners<E>>(name: K, callback: EventCallback<E, K>): () => void;
32
- /**
33
- * Cancel a listener by passing the callback that was originally used to register it.
34
- */
35
- off<K extends keyof EventListeners<E>>(name: K, callback: EventCallback<E, K>): void;
36
- }
37
- declare class EmittedEvent<E extends EventMap, K extends keyof E> {
38
- /**
39
- * Data object emitted with this event.
40
- */
41
- data: E[K];
42
- constructor(data: E[K]);
43
- }
44
- export {};
package/lib/index.d.ts DELETED
@@ -1,21 +0,0 @@
1
- export { App } from "./app.js";
2
- export * from "./signals.js";
3
- export { type Ref, isRef, ref, m, cond, repeat, portal } from "./markup.js";
4
- export { Fragment } from "./views/fragment.js";
5
- export { StoreScope, type StoreScopeProps } from "./views/store-scope.js";
6
- export { RouterStore, type RouteMatchContext } from "./stores/router.js";
7
- export { LanguageStore } from "./stores/language.js";
8
- export { HTTPStore, type HTTPMiddleware } from "./stores/http.js";
9
- export { DialogStore, type DialogProps } from "./stores/dialog.js";
10
- export type { ViewContext } from "./view.js";
11
- export type { StoreContext } from "./store.js";
12
- export type { Markup } from "./markup.js";
13
- export type { InputType, Renderable } from "./types.js";
14
- import type { IntrinsicElements as Elements } from "./types";
15
- declare global {
16
- namespace JSX {
17
- interface IntrinsicElements extends Elements {
18
- [tag: string]: any;
19
- }
20
- }
21
- }