ilha 0.14.3 → 0.14.5

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.
@@ -0,0 +1,43 @@
1
+ import "effect/Scope";
2
+ import { AtomRegistry } from "effect/unstable/reactivity/AtomRegistry";
3
+ import { Effect, Stream } from "effect";
4
+ import { Atom } from "effect/unstable/reactivity";
5
+ //#region src/types.d.ts
6
+ type JsonText = string | number | bigint | boolean | null | undefined;
7
+ /** Runtime prop bag values painted onto elements / passed to components. */
8
+ type PropValue = JsonText | PropBag | StyleObject | EventHandler | AtomHandle<JsonText> | readonly PropValue[];
9
+ type StyleObject = Readonly<Record<string, string | number | null | undefined>>;
10
+ type EventHandler = (event: Event) => void;
11
+ /** Indexed bag — interface so PropValue can recurse without a circular type alias. */
12
+ interface PropBag {
13
+ readonly [key: string]: PropValue | undefined;
14
+ }
15
+ type View = VNode | JsonText | AtomHandle<unknown> | Stream.Stream<View, unknown, unknown> | GeneratorFn | Component | View[] | Iterable<View>;
16
+ declare const Fragment: unique symbol;
17
+ type Fragment = typeof Fragment;
18
+ type ComponentFn = (props: PropBag) => View | Promise<View | undefined> | undefined;
19
+ /** JSX/tag component with its own props shape (Provider, ErrorBoundary, …). */
20
+ type JsxComponent = (props: never) => View | Promise<View | undefined> | Generator<View, View | undefined, View> | undefined;
21
+ interface VNode {
22
+ readonly $$ilha: 1;
23
+ readonly type: string | Fragment | ComponentFn | JsxComponent;
24
+ readonly props: PropBag;
25
+ readonly children: View[];
26
+ readonly key?: string | number;
27
+ }
28
+ type GeneratorFn = () => Generator<Yielded, View | undefined, View>;
29
+ type Yielded = View | Instruction<unknown> | Effect.Effect<unknown, unknown, unknown>;
30
+ interface Instruction<A, E = Error> extends Iterable<Instruction<A, E>, A>, PromiseLike<A> {
31
+ readonly $$ilhaOp: 1;
32
+ readonly effect: Effect.Effect<A, E, AtomRegistry>;
33
+ }
34
+ type Component = (() => View | undefined | Promise<View | undefined>) | GeneratorFn;
35
+ interface AtomHandle<A> {
36
+ readonly $$atom: 1;
37
+ readonly atom: Atom.Atom<A>;
38
+ (): A;
39
+ set: (next: A) => void;
40
+ update: (f: (current: A) => A) => void;
41
+ }
42
+ //#endregion
43
+ export { Instruction as a, VNode as c, Fragment as i, View as l, Component as n, JsxComponent as o, ComponentFn as r, PropBag as s, AtomHandle as t, Yielded as u };
@@ -1,24 +1,28 @@
1
- import { a as VNode, o as View, r as Fragment, t as AtomHandle } from "./types-Cie0Ihl6.js";
1
+ import { c as VNode, i as Fragment, l as View, o as JsxComponent, r as ComponentFn, s as PropBag, t as AtomHandle } from "./types-CUQdA6hR.js";
2
2
  //#region src/jsx-types.d.ts
3
3
  declare namespace JSX {
4
4
  export type Element = View;
5
- export type ElementType = string | ((props: Record<string, unknown>) => View | Promise<View | void> | Generator<unknown, View | void, unknown>);
5
+ export type ElementType = string | ((props: never) => View | Promise<View | undefined> | Generator<View, View | undefined, View> | undefined);
6
6
  export interface ElementChildrenAttribute {
7
- children: {};
7
+ children: View;
8
8
  }
9
9
  /** Scalar attribute value (booleans become presence/absence). */
10
10
  type Attr = string | number | boolean | null | undefined;
11
- /** Values that can bind through `value` / `checked` / `selected`. */
12
- type Bindable<T> = T | AtomHandle<T>;
11
+ /**
12
+ * Values that can bind through `value` / `checked` / `selected`.
13
+ * AtomHandle is invariant in T (via `set`), so constituents of a union T
14
+ * are listed explicitly — e.g. AtomHandle of string for value={string|number}.
15
+ */
16
+ type Bindable<T> = T | AtomHandle<T> | (string extends T ? AtomHandle<string> : never) | (number extends T ? AtomHandle<number> : never) | (boolean extends T ? AtomHandle<boolean> : never);
13
17
  type StyleValue = string | Readonly<Record<string, string | number | null | undefined>> | null | undefined;
14
18
  type Targeted<Target extends globalThis.EventTarget, E extends globalThis.Event> = Omit<E, "currentTarget"> & {
15
19
  readonly currentTarget: Target;
16
20
  };
17
21
  type Handler<Target extends globalThis.EventTarget, E extends globalThis.Event> = {
18
- bivarianceHack(event: Targeted<Target, E>): unknown;
22
+ bivarianceHack: (event: Targeted<Target, E>) => void;
19
23
  }["bivarianceHack"];
20
24
  /** Lowercase DOM event props Ilha binds at runtime. */
21
- type EventProps<Target extends globalThis.EventTarget> = {
25
+ interface EventProps<Target extends globalThis.EventTarget> {
22
26
  onclick?: Handler<Target, globalThis.MouseEvent>;
23
27
  ondblclick?: Handler<Target, globalThis.MouseEvent>;
24
28
  onmousedown?: Handler<Target, globalThis.MouseEvent>;
@@ -69,9 +73,9 @@ declare namespace JSX {
69
73
  ontransitionend?: Handler<Target, globalThis.TransitionEvent>;
70
74
  onload?: Handler<Target, globalThis.Event>;
71
75
  onerror?: Handler<Target, globalThis.Event>;
72
- };
73
- type AriaProps = { [K in `aria-${string}`]?: Attr; };
74
- type DataProps = { [K in `data-${string}`]?: Attr; };
76
+ }
77
+ type AriaProps = Partial<Record<`aria-${string}`, Attr>>;
78
+ type DataProps = Partial<Record<`data-${string}`, Attr>>;
75
79
  /** Shared HTML attributes. Prefer `class` / `for`; `className` / `htmlFor` also work. */
76
80
  type HTMLAttributes<Target extends globalThis.EventTarget = globalThis.HTMLElement> = EventProps<Target> & AriaProps & DataProps & {
77
81
  children?: View;
@@ -125,7 +129,7 @@ declare namespace JSX {
125
129
  };
126
130
  type BodyHTMLAttributes = HTMLAttributes<HTMLBodyElement>;
127
131
  type ButtonHTMLAttributes = HTMLAttributes<HTMLButtonElement> & {
128
- type?: "button" | "submit" | "reset" | (string & {});
132
+ type?: "button" | "submit" | "reset" | string;
129
133
  value?: Bindable<string | number>;
130
134
  name?: Attr;
131
135
  disabled?: Attr;
@@ -178,7 +182,7 @@ declare namespace JSX {
178
182
  height?: number | string;
179
183
  allow?: Attr;
180
184
  allowfullscreen?: Attr;
181
- loading?: "eager" | "lazy" | (string & {});
185
+ loading?: "eager" | "lazy" | string;
182
186
  referrerpolicy?: Attr;
183
187
  sandbox?: Attr;
184
188
  };
@@ -189,8 +193,8 @@ declare namespace JSX {
189
193
  sizes?: Attr;
190
194
  width?: number | string;
191
195
  height?: number | string;
192
- loading?: "eager" | "lazy" | (string & {});
193
- decoding?: "async" | "auto" | "sync" | (string & {});
196
+ loading?: "eager" | "lazy" | string;
197
+ decoding?: "async" | "auto" | "sync" | string;
194
198
  crossorigin?: Attr;
195
199
  referrerpolicy?: Attr;
196
200
  usemap?: Attr;
@@ -571,12 +575,11 @@ declare namespace JSX {
571
575
  "stop-color"?: Attr;
572
576
  "stop-opacity"?: Attr;
573
577
  };
574
- [tag: string]: any;
575
578
  }
576
579
  export {};
577
580
  }
578
581
  //#endregion
579
582
  //#region src/vnode.d.ts
580
- declare function h(type: string | Fragment | ((props: Record<string, unknown>) => unknown), props: Record<string, unknown> | null | undefined, ...rest: View[]): VNode;
583
+ declare const h: (type: string | Fragment | ComponentFn | JsxComponent, props: PropBag | null | undefined, ...rest: View[]) => VNode;
581
584
  //#endregion
582
585
  export { JSX as n, h as t };
@@ -0,0 +1,91 @@
1
+ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
2
+ import * as Option from "effect/Option";
3
+ import * as Result from "effect/Result";
4
+
5
+ //#region src/errors.ts
6
+ const asFailure = (e) => {
7
+ if (Result.isResult(e) && Result.isFailure(e)) {
8
+ const v = Option.getOrUndefined(Result.getFailure(e));
9
+ return Result.fail(v instanceof Error ? v : new Error(String(v)));
10
+ }
11
+ return Result.fail(e instanceof Error ? e : new Error(String(e)));
12
+ };
13
+ /** Normalize any thrown failure into an `Error` instance. */
14
+ const toError = (e) => asFailure(e).pipe(Result.match({
15
+ onFailure: (err) => err,
16
+ onSuccess: () => /* @__PURE__ */ new Error("error")
17
+ }));
18
+ const failureMessage = (e) => toError(e).message;
19
+
20
+ //#endregion
21
+ //#region src/shared.ts
22
+ const KEY_ATTR = "data-ilha-key";
23
+ const SLOT_ATTR = "data-ilha-slot";
24
+ const ISLAND = Symbol.for("ilha.island");
25
+ const ISLAND_MOUNT_INTERNAL = Symbol.for("ilha.islandMountInternal");
26
+ const ISLAND_SLOT_TAG = Symbol.for("ilha.islandSlotTag");
27
+ const objectTag = (value) => Object.prototype.toString.call(value);
28
+ const isBoolean = (value) => value === true || value === false;
29
+ const isString = (value) => objectTag(value) === "[object String]";
30
+ const isNumber = (value) => objectTag(value) === "[object Number]";
31
+ const isBigInt = (value) => objectTag(value) === "[object BigInt]";
32
+ const isFunction = (value) => {
33
+ const tag = objectTag(value);
34
+ return tag === "[object Function]" || tag === "[object AsyncFunction]" || tag === "[object GeneratorFunction]";
35
+ };
36
+ const isObject = (value) => value !== null && objectTag(value) === "[object Object]";
37
+ const skip = (x) => x === null || x === void 0 || isBoolean(x);
38
+ const KEEP = Symbol("ilha.keep");
39
+ const unwrap = (value, keep) => {
40
+ if (AsyncResult.isAsyncResult(value)) {
41
+ if (AsyncResult.isWaiting(value) && keep !== void 0) return KEEP;
42
+ if (AsyncResult.isFailure(value) && !AsyncResult.isWaiting(value)) return String(AsyncResult.error(value) ?? "error");
43
+ const v = AsyncResult.value(value);
44
+ if (v._tag === "Some") return v.value;
45
+ return "";
46
+ }
47
+ return value;
48
+ };
49
+ const errorView = (e) => ({
50
+ $$ilha: 1,
51
+ children: [failureMessage(e)],
52
+ props: { "data-ilha-error": "" },
53
+ type: "pre"
54
+ });
55
+
56
+ //#endregion
57
+ //#region src/types.ts
58
+ const Fragment = Symbol("ilha.Fragment");
59
+
60
+ //#endregion
61
+ //#region src/vnode.ts
62
+ const flatten = (xs) => {
63
+ const out = [];
64
+ for (const x of xs) if (Array.isArray(x)) out.push(...flatten(x));
65
+ else out.push(x);
66
+ return out;
67
+ };
68
+ const h = (type, props, ...rest) => {
69
+ const p = { ...props };
70
+ const fromProps = p.children;
71
+ const { key: rawKey, ...restProps } = p;
72
+ return {
73
+ $$ilha: 1,
74
+ children: flatten([...fromProps === void 0 ? [] : [fromProps], ...rest]),
75
+ key: rawKey,
76
+ props: restProps,
77
+ type
78
+ };
79
+ };
80
+ const isVNode = (x) => {
81
+ if (!isObject(x)) return false;
82
+ return x.$$ilha === 1;
83
+ };
84
+ const isSetupFn = (x) => {
85
+ if (!isFunction(x)) return false;
86
+ const n = x.constructor?.name;
87
+ return n === "GeneratorFunction" || n === "AsyncFunction";
88
+ };
89
+
90
+ //#endregion
91
+ export { skip as _, ISLAND as a, failureMessage as b, KEEP as c, errorView as d, isBigInt as f, isString as g, isObject as h, Fragment as i, KEY_ATTR as l, isNumber as m, isSetupFn as n, ISLAND_MOUNT_INTERNAL as o, isFunction as p, isVNode as r, ISLAND_SLOT_TAG as s, h as t, SLOT_ATTR as u, unwrap as v, toError as x, asFailure as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ilha",
3
- "version": "0.14.3",
3
+ "version": "0.14.5",
4
4
  "description": "Generator-first island UI on Effect",
5
5
  "keywords": [
6
6
  "effect",