bruh 2.0.0-beta.3 → 2.0.0-beta.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.
package/dist/browser.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { isReactive, reactiveDo } from './reactive.mjs';
1
+ import { Reactive, flat, reactiveDo, watch } from './reactive.mjs';
2
2
 
3
3
  const terminalBruhChildToNode = (child) => {
4
4
  if (child instanceof Node)
@@ -11,16 +11,20 @@ const terminalBruhChildToNode = (child) => {
11
11
  const isBruhIterable = (x) => x != null && typeof x === "object" && !(x instanceof Node) && Symbol.iterator in x;
12
12
  const ownedReactivesSymbol = /* @__PURE__ */ Symbol.for("bruh owned reactives");
13
13
  const reactiveTerminalBruhChildToNode = (child) => {
14
- const node = terminalBruhChildToNode(child.value);
14
+ const node = terminalBruhChildToNode(child.peek());
15
15
  let ownedReactives = node[ownedReactivesSymbol] ??= /* @__PURE__ */ new Set();
16
16
  ownedReactives.add(child);
17
17
  let nodeWeakRef = new WeakRef(node);
18
- const stopReacting = child.addReaction(() => {
18
+ const stopReacting = watch([child], () => {
19
19
  const node2 = nodeWeakRef.deref();
20
- if (!node2?.parentNode) {
20
+ if (!node2) {
21
21
  stopReacting();
22
22
  return;
23
23
  }
24
+ if (!node2.parentNode) {
25
+ console.warn("Node has no parent to swap within", { node: node2, child });
26
+ return;
27
+ }
24
28
  const oldNode = node2;
25
29
  const child_ = child;
26
30
  ownedReactives.delete(child);
@@ -29,13 +33,13 @@ const reactiveTerminalBruhChildToNode = (child) => {
29
33
  const nodes = reactiveIterableBruhChildToNodes(child_);
30
34
  oldNode.replaceWith(...nodes);
31
35
  } else {
32
- const node3 = terminalBruhChildToNode(child_.value);
36
+ const node3 = terminalBruhChildToNode(child.value);
33
37
  ownedReactives = node3[ownedReactivesSymbol] ??= /* @__PURE__ */ new Set();
34
38
  ownedReactives.add(child);
35
39
  nodeWeakRef = new WeakRef(node3);
36
40
  oldNode.replaceWith(node3);
37
41
  }
38
- });
42
+ }, { skipFirst: true });
39
43
  return node;
40
44
  };
41
45
  function* reactiveIterableBruhChildToNodes(child) {
@@ -45,46 +49,50 @@ function* reactiveIterableBruhChildToNodes(child) {
45
49
  ownedReactives.add(child);
46
50
  let firstWeakRef = new WeakRef(first);
47
51
  let lastWeakRef = new WeakRef(last);
48
- const stopReacting = child.addReaction(() => {
52
+ const stopReacting = watch([child], () => {
49
53
  const first2 = firstWeakRef.deref();
50
54
  const last2 = lastWeakRef.deref();
51
- if (!first2?.parentNode || !last2?.parentNode) {
55
+ if (!first2 || !last2) {
52
56
  stopReacting();
53
57
  return;
54
58
  }
59
+ if (!first2.parentNode || !last2.parentNode) {
60
+ console.warn("Node range has no parent to swap within", { first: first2, last: last2, child });
61
+ return;
62
+ }
63
+ const child_ = child;
55
64
  const range = document.createRange();
56
65
  range.setStartAfter(first2);
57
66
  if (isBruhIterable(child.value)) {
58
- const child_ = child;
59
67
  range.setEndBefore(last2);
60
68
  range.deleteContents();
61
- first2.after(...bruhChildrenToNodes(child_.value));
69
+ first2.after(...bruhChildrenToNodes(child.value));
62
70
  } else {
63
71
  ownedReactives.delete(child);
64
- const child_ = child;
65
72
  stopReacting();
66
73
  range.setEndAfter(last2);
67
74
  range.deleteContents();
68
75
  first2.replaceWith(reactiveTerminalBruhChildToNode(child_));
69
76
  }
70
- });
77
+ }, { skipFirst: true });
71
78
  yield first;
72
- yield* bruhChildrenToNodes(child.value);
79
+ yield* bruhChildrenToNodes(child.peek());
73
80
  yield last;
74
81
  }
75
82
  function* bruhChildrenToNodes(children) {
76
83
  const partiallyFlattened = Array.isArray(children) ? children.flat(Infinity) : children;
77
84
  for (const child of partiallyFlattened) {
78
- if (!isReactive(child)) {
85
+ if (!(child instanceof Reactive)) {
79
86
  if (isBruhIterable(child))
80
87
  yield* bruhChildrenToNodes(child);
81
88
  else
82
89
  yield terminalBruhChildToNode(child);
83
90
  } else {
84
- if (isBruhIterable(child.value))
85
- yield* reactiveIterableBruhChildToNodes(child);
91
+ const flattened = flat(child);
92
+ if (isBruhIterable(flattened.peek()))
93
+ yield* reactiveIterableBruhChildToNodes(flattened);
86
94
  else
87
- yield reactiveTerminalBruhChildToNode(child);
95
+ yield reactiveTerminalBruhChildToNode(flattened);
88
96
  }
89
97
  }
90
98
  }
@@ -98,12 +106,14 @@ const applyStyles = (element, styles) => {
98
106
  for (const property in styles) {
99
107
  const property_ = property;
100
108
  const maybeReactive = styles[property_];
101
- if (isReactive(maybeReactive))
109
+ if (maybeReactive instanceof Reactive)
102
110
  ownedReactives.add(maybeReactive);
103
- reactiveDo(maybeReactive, (value) => {
111
+ const stopReacting = reactiveDo(maybeReactive, (value) => {
104
112
  const element2 = elementWeakRef.deref();
105
- if (!element2)
113
+ if (!element2) {
114
+ stopReacting?.();
106
115
  return;
116
+ }
107
117
  if (value != null && typeof value !== "boolean")
108
118
  element2.style.setProperty(property, value + "");
109
119
  else
@@ -116,12 +126,14 @@ const applyClasses = (element, classes) => {
116
126
  let elementWeakRef = new WeakRef(element);
117
127
  for (const name in classes) {
118
128
  const maybeReactive = classes[name];
119
- if (isReactive(maybeReactive))
129
+ if (maybeReactive instanceof Reactive)
120
130
  ownedReactives.add(maybeReactive);
121
- reactiveDo(maybeReactive, (value) => {
131
+ const stopReacting = reactiveDo(maybeReactive, (value) => {
122
132
  const element2 = elementWeakRef.deref();
123
- if (!element2)
133
+ if (!element2) {
134
+ stopReacting?.();
124
135
  return;
136
+ }
125
137
  element2.classList.toggle(name, value === true);
126
138
  });
127
139
  }
@@ -131,12 +143,14 @@ const applyAttributes = (element, attributes) => {
131
143
  let elementWeakRef = new WeakRef(element);
132
144
  for (const name in attributes) {
133
145
  const maybeReactive = attributes[name];
134
- if (isReactive(maybeReactive))
146
+ if (maybeReactive instanceof Reactive)
135
147
  ownedReactives.add(maybeReactive);
136
- reactiveDo(attributes[name], (value) => {
148
+ const stopReacting = reactiveDo(attributes[name], (value) => {
137
149
  const element2 = elementWeakRef.deref();
138
- if (!element2)
150
+ if (!element2) {
151
+ stopReacting?.();
139
152
  return;
153
+ }
140
154
  if (typeof value === "boolean")
141
155
  element2.toggleAttribute(name, value);
142
156
  else if (value != null)
@@ -147,12 +161,20 @@ const applyAttributes = (element, attributes) => {
147
161
  }
148
162
  };
149
163
  const t = (textContent) => {
150
- if (!isReactive(textContent))
164
+ if (!(textContent instanceof Reactive))
151
165
  return document.createTextNode(textContent + "");
152
- const node = document.createTextNode(textContent.value + "");
153
- textContent.addReaction(() => {
154
- node.textContent = textContent.value + "";
155
- });
166
+ const node = document.createTextNode(textContent.peek() + "");
167
+ const ownedReactives = node[ownedReactivesSymbol] ??= /* @__PURE__ */ new Set();
168
+ ownedReactives.add(textContent);
169
+ let nodeWeakRef = new WeakRef(node);
170
+ const stopReacting = watch([textContent], () => {
171
+ const node2 = nodeWeakRef.deref();
172
+ if (!node2) {
173
+ stopReacting();
174
+ return;
175
+ }
176
+ node2.textContent = textContent.value + "";
177
+ }, { skipFirst: true });
156
178
  return node;
157
179
  };
158
180
  const jsx = (nameOrComponent, props_, key) => {
@@ -166,7 +188,7 @@ const jsx = (nameOrComponent, props_, key) => {
166
188
  const name = nameOrComponent;
167
189
  const props = props_;
168
190
  let options = {};
169
- if (typeof props.bruh === "object" && !isReactive(props.bruh)) {
191
+ if (typeof props.bruh === "object" && !(props.bruh instanceof Reactive)) {
170
192
  options = props.bruh;
171
193
  delete props.bruh;
172
194
  }
@@ -180,11 +202,11 @@ const jsx = (nameOrComponent, props_, key) => {
180
202
  );
181
203
  delete props.children;
182
204
  }
183
- if ("style" in props && props.style != null && typeof props.style === "object" && !isReactive(props.style) && isElementWithStyle(element)) {
205
+ if ("style" in props && props.style != null && typeof props.style === "object" && !(props.style instanceof Reactive) && isElementWithStyle(element)) {
184
206
  applyStyles(element, props.style);
185
207
  delete props.style;
186
208
  }
187
- if ("class" in props && props.class != null && typeof props.class === "object" && !isReactive(props.class)) {
209
+ if ("class" in props && props.class != null && typeof props.class === "object" && !(props.class instanceof Reactive)) {
188
210
  applyClasses(element, props.class);
189
211
  delete props.class;
190
212
  }
@@ -1 +1 @@
1
- {"version":3,"file":"browser.mjs","sources":["../src/dom/index.browser.mts"],"sourcesContent":["import { isReactive, reactiveDo } from \"../reactive/index.mts\"\nimport type { Reactive, MaybeReactive } from \"../reactive/index.mts\"\nimport type {\n PropertyWiseOr,\n LikelyAsString,\n LikelyAsAbsent,\n LikelyAsBoolean\n} from \"./types.mts\"\nimport type { PropertiesHyphen as Styles } from \"csstype\"\nimport type {\n ElementType,\n\n HTMLTag,\n SVGTag,\n MathMLTag,\n\n Namespace,\n HTMLNamespace,\n SVGNamespace,\n MathMLNamespace,\n\n ElementToEventMap,\n ElementToAttributes\n} from \"html-info\"\n\nexport type TerminalBruhChild =\n | Node\n | LikelyAsString\n | LikelyAsAbsent\n\nexport type TerminalBruhChildOutputNode<Child extends TerminalBruhChild>\n = Child extends Node\n ? Child\n : Child extends LikelyAsString\n ? Text\n : Child extends LikelyAsAbsent\n ? Comment\n : Node\n\n// disallow a reactive from directly holding a reactive\nexport type FlatBruhChild =\n | MaybeReactive<TerminalBruhChild>\n | Reactive<TerminalBruhChild | Iterable<BruhChild>>\n\nexport type BruhChild =\n | FlatBruhChild\n | Iterable<BruhChild>\n\nexport type StylesToApply = {\n [Property in keyof Styles]: MaybeReactive<Styles[Property] | LikelyAsAbsent>\n}\n\nexport interface ClassesToApply {\n [className: string]: MaybeReactive<LikelyAsBoolean>\n}\n\nexport type AttributesToApply<\n Name extends string,\n NS extends Namespace = HTMLNamespace\n> = {\n [Attribute in keyof ElementToAttributes<Name, NS>]?:\n MaybeReactive<ElementToAttributes<Name, NS>[Attribute] | LikelyAsBoolean>\n}\n\ntype EventMapToListenerProps<EventMap> = {\n [E in ((keyof EventMap) & string) as `on${E}`]:\n (event: EventMap[E]) => void\n}\n\ntype AttributeMapToProps<AttributeMap> = {\n [Attribute in keyof AttributeMap]:\n MaybeReactive<AttributeMap[Attribute] | LikelyAsBoolean>\n | ( Attribute extends \"style\"\n ? StylesToApply\n : Attribute extends \"class\"\n ? ClassesToApply\n : never\n )\n}\n\nexport interface BruhOptions {\n namespace?: Namespace\n}\n\ninterface BaseBruhProps {\n bruh?: BruhOptions,\n children?: BruhChild\n}\n\nexport type BruhProps<\n Name extends string,\n NS extends string = HTMLNamespace\n>\n = BaseBruhProps\n & (\n NS extends HTMLNamespace\n ? { bruh?: { namespace?: HTMLNamespace } }\n : { bruh: { namespace: NS } }\n )\n & Partial<\n EventMapToListenerProps<ElementToEventMap<Name, NS>> &\n AttributeMapToProps<ElementToAttributes<Name, NS>>\n >\n\nexport type HTMLTagToBruhProps = { [Name in HTMLTag]: BruhProps<Name, HTMLNamespace> }\nexport type SVGTagToBruhProps = { [Name in SVGTag]: BruhProps<Name, SVGNamespace> }\nexport type MathMLTagToBruhProps = { [Name in MathMLTag]: BruhProps<Name, MathMLNamespace> }\n\nexport type TagToBruhProps =\n PropertyWiseOr<\n HTMLTagToBruhProps,\n PropertyWiseOr<\n SVGTagToBruhProps,\n MathMLTagToBruhProps\n >\n >\n\nexport namespace JSX {\n /** @see https://www.typescriptlang.org/docs/handbook/jsx.html#children-type-checking */\n export interface ElementChildrenAttribute { children: {} }\n\n /** @see https://www.typescriptlang.org/docs/handbook/jsx.html#attribute-type-checking */\n export interface IntrinsicElements extends TagToBruhProps {}\n\n export type Element = any\n\n export type ElementType = HTMLTag | SVGTag | MathMLTag | ((props: any) => Element)\n}\n\n// Coerces input into a DOM node, if it isn't already one\nconst terminalBruhChildToNode: {\n <Child extends TerminalBruhChild>(child: Child): TerminalBruhChildOutputNode<Child>\n} = (child: TerminalBruhChild): any => {\n // Existing DOM nodes are untouched\n if (child instanceof Node)\n return child\n // Nullish and booleans are ignored\n else if (child == null || typeof child === \"boolean\")\n return document.createComment(child + \"\")\n // Anything else is treated as text\n else\n return document.createTextNode(child + \"\")\n}\n\nconst isBruhIterable = (x: unknown): x is Iterable<BruhChild> =>\n x != null &&\n typeof x === \"object\" &&\n !(x instanceof Node) &&\n Symbol.iterator in x\n\nexport const ownedReactivesSymbol = Symbol.for(\"bruh owned reactives\")\n\ndeclare global {\n interface Node {\n [ownedReactivesSymbol]?: Set<Reactive<unknown>>\n }\n}\n\n// Auto-swapping single reactive node\nconst reactiveTerminalBruhChildToNode: {\n <Child extends TerminalBruhChild>(child: Reactive<Child>): TerminalBruhChildOutputNode<Child>\n} = (child: Reactive<TerminalBruhChild>): any => {\n const node = terminalBruhChildToNode(child.value)\n\n let ownedReactives = node[ownedReactivesSymbol] ??= new Set()\n ownedReactives.add(child)\n\n let nodeWeakRef = new WeakRef(node)\n\n const stopReacting = child.addReaction(() => {\n const node = nodeWeakRef.deref()\n\n // Stop swapping if no longer possible\n if (!node?.parentNode) {\n stopReacting()\n return\n }\n\n const oldNode = node as typeof node & ChildNode\n const child_ = child as Reactive<BruhChild>\n\n ownedReactives.delete(child)\n\n // If an iterable now, stop swapping, then switch to reactive iterable swapping\n if (isBruhIterable(child.value)) {\n stopReacting()\n const nodes = reactiveIterableBruhChildToNodes(child_ as Reactive<Iterable<BruhChild>>)\n oldNode.replaceWith(...nodes)\n }\n // Normal swap\n else {\n const node = terminalBruhChildToNode(child_.value as TerminalBruhChild)\n ownedReactives = node[ownedReactivesSymbol] ??= new Set()\n ownedReactives.add(child)\n nodeWeakRef = new WeakRef(node)\n oldNode.replaceWith(node)\n }\n })\n\n return node\n}\n\n// Auto-swapping reactive iterable of nodes\nfunction * reactiveIterableBruhChildToNodes(child: Reactive<Iterable<BruhChild>>): IterableIterator<Node> {\n // Markers owned by the swapper here itself, so that\n // the values in the iterable can be swapped separately\n const first = document.createComment(\"[\")\n const last = document.createComment(\"]\")\n\n let ownedReactives = first[ownedReactivesSymbol] ??= new Set()\n ownedReactives.add(child)\n\n let firstWeakRef = new WeakRef(first)\n let lastWeakRef = new WeakRef(last)\n\n const stopReacting = child.addReaction(() => {\n const first = firstWeakRef.deref()\n const last = lastWeakRef.deref()\n\n // Stop swapping if there is no parent to swap within\n if (!first?.parentNode || !last?.parentNode) {\n stopReacting()\n return\n }\n\n // Make a range starting after the first marker\n const range = document.createRange()\n range.setStartAfter(first)\n\n // Normal swap, replacing content between the first and last markers\n if (isBruhIterable(child.value)) {\n const child_ = child as Reactive<Iterable<BruhChild>>\n\n range.setEndBefore(last)\n range.deleteContents()\n first.after(...bruhChildrenToNodes(child_.value))\n }\n // Switch to single swapping node by replacing everything\n else {\n ownedReactives.delete(child)\n\n const child_ = child as unknown as Reactive<TerminalBruhChild>\n\n stopReacting()\n range.setEndAfter(last)\n range.deleteContents()\n first.replaceWith(reactiveTerminalBruhChildToNode(child_))\n }\n })\n\n yield first\n yield* bruhChildrenToNodes(child.value)\n yield last\n}\n\n// Processes bruh children into an iterable of DOM nodes\n// Reactive values are automatically replaced, so the output must be placed into a parent node\n// before any top level (after flattening iterables) reactions run\nexport function * bruhChildrenToNodes(children: Iterable<BruhChild>): IterableIterator<Node> {\n const partiallyFlattened =\n Array.isArray(children)\n ? children.flat<BruhChild, number>(Infinity)\n : children\n\n for (const child of partiallyFlattened) {\n if (!isReactive(child)) {\n if (isBruhIterable(child))\n yield* bruhChildrenToNodes(child)\n else\n yield terminalBruhChildToNode(child)\n }\n else {\n if (isBruhIterable(child.value))\n yield* reactiveIterableBruhChildToNodes(child as Reactive<Iterable<BruhChild>>)\n else\n yield reactiveTerminalBruhChildToNode(child as Reactive<TerminalBruhChild>)\n }\n }\n}\n\n//#endregion\n\n//#region Reactive-aware element helper functions e.g. applyAttributes()\n\ntype ElementWithStyle = HTMLElement | SVGElement | MathMLElement\n\n// https://w3c.github.io/csswg-drafts/cssom/#the-elementcssinlinestyle-mixin\nconst isElementWithStyle = <T extends Element>(element: T): element is (T & ElementWithStyle) =>\n // @ts-ignore\n element.style instanceof CSSStyleDeclaration\n\n/**\n * Style attribute rules from an object with\n * potentially reactive and/or set as absent values\n */\nexport const applyStyles = <E extends ElementWithStyle>(\n element: E,\n styles: StylesToApply\n) => {\n const ownedReactives = element[ownedReactivesSymbol] ??= new Set()\n let elementWeakRef = new WeakRef(element)\n\n for (const property in styles) {\n const property_ = property as keyof StylesToApply\n const maybeReactive = styles[property_]\n if (isReactive(maybeReactive))\n ownedReactives.add(maybeReactive)\n\n reactiveDo(maybeReactive, value => {\n const element = elementWeakRef.deref()\n if (!element)\n return\n\n if (value != null && typeof value !== \"boolean\")\n element.style.setProperty (property, value + \"\")\n else\n element.style.removeProperty(property)\n })\n }\n}\n\n/**\n * Class list from an object mapping from\n * class names to potentially reactive booleans\n */\nexport const applyClasses = (\n element: Element,\n classes: ClassesToApply\n) => {\n const ownedReactives = element[ownedReactivesSymbol] ??= new Set()\n let elementWeakRef = new WeakRef(element)\n\n for (const name in classes) {\n const maybeReactive = classes[name]\n if (isReactive(maybeReactive))\n ownedReactives.add(maybeReactive)\n\n reactiveDo(maybeReactive, value => {\n const element = elementWeakRef.deref()\n if (!element)\n return\n\n // without coercing to a boolean, `undefined` would toggle instead of forcing removal\n element.classList.toggle(name, value === true)\n })\n }\n}\n\n/**\n * Attributes from an object with\n * potentially reactive and/or set as absent values\n */\nexport const applyAttributes = <\n Name extends string,\n NS extends Namespace = HTMLNamespace\n>(\n element: ElementType<Name, NS>,\n attributes: AttributesToApply<Name, NS>\n) => {\n const ownedReactives = element[ownedReactivesSymbol] ??= new Set()\n let elementWeakRef = new WeakRef(element)\n\n for (const name in attributes) {\n const maybeReactive = attributes[name]\n if (isReactive(maybeReactive))\n ownedReactives.add(maybeReactive)\n\n reactiveDo<ElementToAttributes<Name, NS>[typeof name] | LikelyAsBoolean>(attributes[name], value => {\n const element = elementWeakRef.deref()\n if (!element)\n return\n\n if (typeof value === \"boolean\")\n element.toggleAttribute(name, value)\n else if (value != null)\n element.setAttribute (name, value + \"\")\n else\n element.removeAttribute(name)\n })\n }\n}\n\n//#endregion\n\n//#region t()\n\n// Text nodes\nexport const t = (textContent: MaybeReactive<LikelyAsString>) => {\n // Non-reactive values are just text nodes\n if (!isReactive(textContent))\n return document.createTextNode(textContent + \"\")\n\n // Reactive values auto-update the node's text content\n const node = document.createTextNode(textContent.value + \"\")\n textContent.addReaction(() => {\n node.textContent = textContent.value + \"\"\n })\n return node\n}\n\n//#endregion\n\n//#region JSX integration\n\ndeclare global {\n interface String {\n startsWith<Prefix extends string>(\n prefix: Prefix,\n position?: 0\n ): this is `${Prefix}${string}`\n }\n}\n\nexport const jsx: {\n /**\n * Create an HTML element\n */\n <\n Name extends HTMLTag\n >(\n name: Name,\n props: HTMLTagToBruhProps[Name],\n key?: string\n ):\n HTMLElementTagNameMap[Name]\n\n /**\n * Create an SVG element\n */\n <\n Name extends SVGTag\n >(\n name: Name,\n props: SVGTagToBruhProps[Name],\n key?: string\n ):\n SVGElementTagNameMap[Name]\n\n /**\n * Create a MathML element\n */\n <\n Name extends MathMLTag\n >(\n name: Name,\n props: MathMLTagToBruhProps[Name],\n key?: string\n ):\n MathMLElementTagNameMap[Name]\n\n /**\n * Create an element\n */\n <\n Name extends string,\n NS extends Namespace = HTMLNamespace\n >(\n name: Name,\n props: BruhProps<Name, NS>,\n key?: string\n ):\n ElementType<Name, NS>\n\n /**\n * Call a function as a JSX component\n */\n <\n Props extends Record<any, unknown>,\n Result\n >(\n component: (props: Props) => Result,\n props: Props,\n key?: string\n ): Result\n} =\n<\n Name extends string,\n NS extends Namespace = HTMLNamespace\n>\n(\n nameOrComponent: Name | Function,\n props_: Record<any, unknown>,\n key?: string\n) => {\n if (key !== undefined)\n props_.key = key\n\n // It must be a component, as bruh components are just functions\n // Due to JSX, this would mean a function with only one parameter - props\n // This object includes all of the normal props and a \"children\" key\n if (typeof nameOrComponent !== \"string\") {\n const component = nameOrComponent\n const props = props_ as Record<any, unknown>\n\n return component(props)\n }\n\n const name = nameOrComponent\n const props = props_ as BruhProps<Name, NS>\n\n // Extract explicit options from the bruh prop\n let options: BruhOptions = {}\n if (typeof props.bruh === \"object\" && !isReactive(props.bruh)) {\n options = props.bruh\n delete props.bruh\n }\n const { namespace } = options\n\n // Make an element with optional namespace\n const element =\n namespace\n ? document.createElementNS(namespace, name) as ElementType<Name, NS>\n : document.createElement ( name) as ElementType<Name, NS>\n\n if (\"children\" in props) {\n element.append(\n ...bruhChildrenToNodes(\n isBruhIterable(props.children)\n ? props.children\n : [props.children]\n )\n )\n\n delete props.children\n }\n\n // Apply overloaded props, if possible\n\n // Inline style object\n if (\n \"style\" in props &&\n props.style != null &&\n typeof props.style === \"object\" &&\n !isReactive(props.style) &&\n isElementWithStyle(element)\n ) {\n applyStyles(element, props.style)\n delete props.style\n }\n\n // Classes object\n if (\n \"class\" in props &&\n props.class != null &&\n typeof props.class === \"object\" &&\n !isReactive(props.class)\n ) {\n applyClasses(element, props.class)\n delete props.class\n }\n\n for (const name_ in props) {\n const name = name_ as string & (keyof typeof props)\n // Event listener functions\n if (typeof props[name] === \"function\" && name.startsWith(\"on\")) {\n element.addEventListener(name.slice(2), props[name] as any)\n delete props[name]\n }\n }\n\n // The rest of the props are attributes\n applyAttributes(element, props as AttributesToApply<Name, NS>)\n\n return element\n}\n\nexport const Fragment =\n <Children extends BruhChild>\n (props: { children: Children }) => props.children\n\n//#endregion\n\n\nexport class BruhText extends HTMLElement {\n static hydrated: { readonly [tag: string]: ReadonlySet<Text> } = {}\n\n constructor() {\n super()\n\n const textNode = document.createTextNode(this.textContent!)\n\n const tag = this.getAttribute(\"tag\")\n if (tag) {\n const set = (BruhText.hydrated as { [tag: string]: Set<Text> })[tag] ??= new Set()\n set.add(textNode)\n }\n\n this.replaceWith(textNode)\n }\n}\n\ncustomElements.define(\"bruh-text\", BruhText)\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"bruh-text\": BruhText\n }\n}\ndeclare module \"html-info\" {\n interface HTMLTagToAttributes {\n \"bruh-text\": {\n \"tag\"?: string\n }\n }\n}\n"],"names":["node","first","last","element","props","name"],"mappings":"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"}
1
+ {"version":3,"file":"browser.mjs","sources":["../src/dom/index.browser.mts"],"sourcesContent":["import { reactiveDo, flat, watch } from \"../reactive/index.mts\"\nimport { Reactive, type MaybeReactive, type NestedReactive } from \"../reactive/index.mts\"\nimport type {\n PropertyWiseOr,\n LikelyAsString,\n LikelyAsAbsent,\n LikelyAsBoolean\n} from \"./types.mts\"\nimport type { PropertiesHyphen as Styles } from \"csstype\"\nimport type {\n ElementType,\n\n HTMLTag,\n SVGTag,\n MathMLTag,\n\n Namespace,\n HTMLNamespace,\n SVGNamespace,\n MathMLNamespace,\n\n ElementToEventMap,\n ElementToAttributes\n} from \"html-info\"\n\nexport type TerminalBruhChild =\n | Node\n | LikelyAsString\n | LikelyAsAbsent\n\nexport type TerminalBruhChildOutputNode<Child extends TerminalBruhChild>\n = Child extends Node\n ? Child\n : Child extends LikelyAsString\n ? Text\n : Child extends LikelyAsAbsent\n ? Comment\n : Node\n\nexport type BruhChild =\n | MaybeReactive<TerminalBruhChild>\n | Iterable<BruhChild>\n | NestedReactive<TerminalBruhChild | Iterable<BruhChild>>\n\nexport type StylesToApply = {\n [Property in keyof Styles]: MaybeReactive<Styles[Property] | LikelyAsAbsent>\n}\n\nexport interface ClassesToApply {\n [className: string]: MaybeReactive<LikelyAsBoolean>\n}\n\nexport type AttributesToApply<\n Name extends string,\n NS extends Namespace = HTMLNamespace\n> = {\n [Attribute in keyof ElementToAttributes<Name, NS>]?:\n MaybeReactive<ElementToAttributes<Name, NS>[Attribute] | LikelyAsBoolean>\n}\n\ntype EventMapToListenerProps<EventMap> = {\n [E in ((keyof EventMap) & string) as `on${E}`]:\n (event: EventMap[E]) => void\n}\n\ntype AttributeMapToProps<AttributeMap> = {\n [Attribute in keyof AttributeMap]:\n MaybeReactive<AttributeMap[Attribute] | LikelyAsBoolean>\n | ( Attribute extends \"style\"\n ? StylesToApply\n : Attribute extends \"class\"\n ? ClassesToApply\n : never\n )\n}\n\nexport interface BruhOptions {\n namespace?: Namespace\n}\n\ninterface BaseBruhProps {\n bruh?: BruhOptions,\n children?: BruhChild\n}\n\nexport type BruhProps<\n Name extends string,\n NS extends string = HTMLNamespace\n>\n = BaseBruhProps\n & (\n NS extends HTMLNamespace\n ? { bruh?: { namespace?: HTMLNamespace } }\n : { bruh: { namespace: NS } }\n )\n & Partial<\n EventMapToListenerProps<ElementToEventMap<Name, NS>> &\n AttributeMapToProps<ElementToAttributes<Name, NS>>\n >\n\nexport type HTMLTagToBruhProps = { [Name in HTMLTag]: BruhProps<Name, HTMLNamespace> }\nexport type SVGTagToBruhProps = { [Name in SVGTag]: BruhProps<Name, SVGNamespace> }\nexport type MathMLTagToBruhProps = { [Name in MathMLTag]: BruhProps<Name, MathMLNamespace> }\n\nexport type TagToBruhProps =\n PropertyWiseOr<\n HTMLTagToBruhProps,\n PropertyWiseOr<\n SVGTagToBruhProps,\n MathMLTagToBruhProps\n >\n >\n\nexport namespace JSX {\n /** @see https://www.typescriptlang.org/docs/handbook/jsx.html#children-type-checking */\n export interface ElementChildrenAttribute { children: {} }\n\n /** @see https://www.typescriptlang.org/docs/handbook/jsx.html#attribute-type-checking */\n export interface IntrinsicElements extends TagToBruhProps {}\n\n export type Element = any\n\n export type ElementType = HTMLTag | SVGTag | MathMLTag | ((props: any) => Element)\n}\n\n// Coerces input into a DOM node, if it isn't already one\nconst terminalBruhChildToNode: {\n <Child extends TerminalBruhChild>(child: Child): TerminalBruhChildOutputNode<Child>\n} = (child: TerminalBruhChild): any => {\n // Existing DOM nodes are untouched\n if (child instanceof Node)\n return child\n // Nullish and booleans are ignored\n else if (child == null || typeof child === \"boolean\")\n return document.createComment(child + \"\")\n // Anything else is treated as text\n else\n return document.createTextNode(child + \"\")\n}\n\nconst isBruhIterable = (x: unknown): x is Iterable<BruhChild> =>\n x != null &&\n typeof x === \"object\" &&\n !(x instanceof Node) &&\n Symbol.iterator in x\n\nexport const ownedReactivesSymbol = Symbol.for(\"bruh owned reactives\")\n\ndeclare global {\n interface Node {\n [ownedReactivesSymbol]?: Set<Reactive<unknown>>\n }\n}\n\n// Auto-swapping single reactive node\nconst reactiveTerminalBruhChildToNode: {\n <Child extends TerminalBruhChild>(child: Reactive<Child>): TerminalBruhChildOutputNode<Child>\n} = (child: Reactive<TerminalBruhChild>): any => {\n const node = terminalBruhChildToNode(child.peek())\n\n let ownedReactives = node[ownedReactivesSymbol] ??= new Set()\n ownedReactives.add(child)\n\n let nodeWeakRef = new WeakRef(node)\n\n const stopReacting = watch([child], () => {\n const node = nodeWeakRef.deref()\n\n // Stop swapping if no longer possible\n if (!node) {\n stopReacting()\n return\n }\n if (!node.parentNode) {\n console.warn(\"Node has no parent to swap within\", { node, child })\n return\n }\n\n const oldNode = node as typeof node & ChildNode\n const child_ = child as Reactive<BruhChild>\n\n ownedReactives.delete(child)\n\n // If an iterable now, stop swapping, then switch to reactive iterable swapping\n if (isBruhIterable(child.value)) {\n stopReacting()\n const nodes = reactiveIterableBruhChildToNodes(child_ as Reactive<Iterable<BruhChild>>)\n oldNode.replaceWith(...nodes)\n }\n // Normal swap\n else {\n const node = terminalBruhChildToNode(child.value)\n ownedReactives = node[ownedReactivesSymbol] ??= new Set()\n ownedReactives.add(child)\n nodeWeakRef = new WeakRef(node)\n oldNode.replaceWith(node)\n }\n }, { skipFirst: true })\n\n return node\n}\n\n// Auto-swapping reactive iterable of nodes\nfunction * reactiveIterableBruhChildToNodes(child: Reactive<Iterable<BruhChild>>): IterableIterator<Node> {\n // Markers owned by the swapper here itself, so that\n // the values in the iterable can be swapped separately\n const first = document.createComment(\"[\")\n const last = document.createComment(\"]\")\n\n let ownedReactives = first[ownedReactivesSymbol] ??= new Set()\n ownedReactives.add(child)\n\n let firstWeakRef = new WeakRef(first)\n let lastWeakRef = new WeakRef(last)\n\n const stopReacting = watch([child], () => {\n const first = firstWeakRef.deref()\n const last = lastWeakRef.deref()\n\n // Stop swapping if there is no parent to swap within\n if (!first || !last) {\n stopReacting()\n return\n }\n if (!first.parentNode || !last.parentNode) {\n console.warn(\"Node range has no parent to swap within\", { first, last, child })\n return\n }\n\n const child_ = child as Reactive<BruhChild>\n\n // Make a range starting after the first marker\n const range = document.createRange()\n range.setStartAfter(first)\n\n // Normal swap, replacing content between the first and last markers\n if (isBruhIterable(child.value)) {\n range.setEndBefore(last)\n range.deleteContents()\n first.after(...bruhChildrenToNodes(child.value))\n }\n // Switch to single swapping node by replacing everything\n else {\n ownedReactives.delete(child)\n\n stopReacting()\n range.setEndAfter(last)\n range.deleteContents()\n first.replaceWith(reactiveTerminalBruhChildToNode(child_ as Reactive<TerminalBruhChild>))\n }\n }, { skipFirst: true })\n\n yield first\n yield* bruhChildrenToNodes(child.peek())\n yield last\n}\n\n// Processes bruh children into an iterable of DOM nodes\n// Reactive values are automatically replaced, so the output must be placed into a parent node\n// before any top level (after flattening iterables) reactions run\nexport function * bruhChildrenToNodes(children: Iterable<BruhChild>): IterableIterator<Node> {\n const partiallyFlattened =\n Array.isArray(children)\n ? children.flat<BruhChild, number>(Infinity)\n : children\n\n for (const child of partiallyFlattened) {\n if (!(child instanceof Reactive)) {\n if (isBruhIterable(child))\n yield* bruhChildrenToNodes(child)\n else\n yield terminalBruhChildToNode(child)\n }\n else {\n const flattened = flat(child as NestedReactive<Iterable<BruhChild> | TerminalBruhChild>)\n\n if (isBruhIterable(flattened.peek()))\n yield* reactiveIterableBruhChildToNodes(flattened as Reactive<Iterable<BruhChild>>)\n else\n yield reactiveTerminalBruhChildToNode(flattened as Reactive<TerminalBruhChild>)\n }\n }\n}\n\n//#endregion\n\n//#region Reactive-aware element helper functions e.g. applyAttributes()\n\ntype ElementWithStyle = HTMLElement | SVGElement | MathMLElement\n\n// https://w3c.github.io/csswg-drafts/cssom/#the-elementcssinlinestyle-mixin\nconst isElementWithStyle = <T extends Element>(element: T): element is (T & ElementWithStyle) =>\n // @ts-ignore\n element.style instanceof CSSStyleDeclaration\n\n/**\n * Style attribute rules from an object with\n * potentially reactive and/or set as absent values\n */\nexport const applyStyles = <E extends ElementWithStyle>(\n element: E,\n styles: StylesToApply\n) => {\n const ownedReactives = element[ownedReactivesSymbol] ??= new Set()\n let elementWeakRef = new WeakRef(element)\n\n for (const property in styles) {\n const property_ = property as keyof StylesToApply\n const maybeReactive = styles[property_]\n if (maybeReactive instanceof Reactive)\n ownedReactives.add(maybeReactive)\n\n const stopReacting = reactiveDo(maybeReactive, value => {\n const element = elementWeakRef.deref()\n if (!element) {\n stopReacting?.()\n return\n }\n\n if (value != null && typeof value !== \"boolean\")\n element.style.setProperty (property, value + \"\")\n else\n element.style.removeProperty(property)\n })\n }\n}\n\n/**\n * Class list from an object mapping from\n * class names to potentially reactive booleans\n */\nexport const applyClasses = (\n element: Element,\n classes: ClassesToApply\n) => {\n const ownedReactives = element[ownedReactivesSymbol] ??= new Set()\n let elementWeakRef = new WeakRef(element)\n\n for (const name in classes) {\n const maybeReactive = classes[name]\n if (maybeReactive instanceof Reactive)\n ownedReactives.add(maybeReactive)\n\n const stopReacting = reactiveDo(maybeReactive, value => {\n const element = elementWeakRef.deref()\n if (!element) {\n stopReacting?.()\n return\n }\n\n // without coercing to a boolean, `undefined` would toggle instead of forcing removal\n element.classList.toggle(name, value === true)\n })\n }\n}\n\n/**\n * Attributes from an object with\n * potentially reactive and/or set as absent values\n */\nexport const applyAttributes = <\n Name extends string,\n NS extends Namespace = HTMLNamespace\n>(\n element: ElementType<Name, NS>,\n attributes: AttributesToApply<Name, NS>\n) => {\n const ownedReactives = element[ownedReactivesSymbol] ??= new Set()\n let elementWeakRef = new WeakRef(element)\n\n for (const name in attributes) {\n const maybeReactive = attributes[name]\n if (maybeReactive instanceof Reactive)\n ownedReactives.add(maybeReactive)\n\n const stopReacting = reactiveDo<ElementToAttributes<Name, NS>[typeof name] | LikelyAsBoolean>(attributes[name], value => {\n const element = elementWeakRef.deref()\n if (!element) {\n stopReacting?.()\n return\n }\n\n if (typeof value === \"boolean\")\n element.toggleAttribute(name, value)\n else if (value != null)\n element.setAttribute (name, value + \"\")\n else\n element.removeAttribute(name)\n })\n }\n}\n\n//#endregion\n\n//#region t()\n\n// Text nodes\nexport const t = (textContent: MaybeReactive<LikelyAsString>) => {\n // Non-reactive values are just text nodes\n if (!(textContent instanceof Reactive))\n return document.createTextNode(textContent + \"\")\n\n // Reactive values auto-update the node's text content\n const node = document.createTextNode(textContent.peek() + \"\")\n const ownedReactives = node[ownedReactivesSymbol] ??= new Set()\n ownedReactives.add(textContent)\n let nodeWeakRef = new WeakRef(node)\n\n const stopReacting = watch([textContent], () => {\n const node = nodeWeakRef.deref()\n if (!node) {\n stopReacting()\n return\n }\n\n node.textContent = textContent.value + \"\"\n }, { skipFirst: true })\n return node\n}\n\n//#endregion\n\n//#region JSX integration\n\ndeclare global {\n interface String {\n startsWith<Prefix extends string>(\n prefix: Prefix,\n position?: 0\n ): this is `${Prefix}${string}`\n }\n}\n\nexport const jsx: {\n /**\n * Create an HTML element\n */\n <\n Name extends HTMLTag\n >(\n name: Name,\n props: HTMLTagToBruhProps[Name],\n key?: string\n ):\n HTMLElementTagNameMap[Name]\n\n /**\n * Create an SVG element\n */\n <\n Name extends SVGTag\n >(\n name: Name,\n props: SVGTagToBruhProps[Name],\n key?: string\n ):\n SVGElementTagNameMap[Name]\n\n /**\n * Create a MathML element\n */\n <\n Name extends MathMLTag\n >(\n name: Name,\n props: MathMLTagToBruhProps[Name],\n key?: string\n ):\n MathMLElementTagNameMap[Name]\n\n /**\n * Create an element\n */\n <\n Name extends string,\n NS extends Namespace = HTMLNamespace\n >(\n name: Name,\n props: BruhProps<Name, NS>,\n key?: string\n ):\n ElementType<Name, NS>\n\n /**\n * Call a function as a JSX component\n */\n <\n Props extends Record<any, unknown>,\n Result\n >(\n component: (props: Props) => Result,\n props: Props,\n key?: string\n ): Result\n} =\n<\n Name extends string,\n NS extends Namespace = HTMLNamespace\n>\n(\n nameOrComponent: Name | Function,\n props_: Record<any, unknown>,\n key?: string\n) => {\n if (key !== undefined)\n props_.key = key\n\n // It must be a component, as bruh components are just functions\n // Due to JSX, this would mean a function with only one parameter - props\n // This object includes all of the normal props and a \"children\" key\n if (typeof nameOrComponent !== \"string\") {\n const component = nameOrComponent\n const props = props_ as Record<any, unknown>\n\n return component(props)\n }\n\n const name = nameOrComponent\n const props = props_ as BruhProps<Name, NS>\n\n // Extract explicit options from the bruh prop\n let options: BruhOptions = {}\n if (typeof props.bruh === \"object\" && !(props.bruh instanceof Reactive)) {\n options = props.bruh\n delete props.bruh\n }\n const { namespace } = options\n\n // Make an element with optional namespace\n const element =\n namespace\n ? document.createElementNS(namespace, name) as ElementType<Name, NS>\n : document.createElement ( name) as ElementType<Name, NS>\n\n if (\"children\" in props) {\n element.append(\n ...bruhChildrenToNodes(\n isBruhIterable(props.children)\n ? props.children\n : [props.children]\n )\n )\n\n delete props.children\n }\n\n // Apply overloaded props, if possible\n\n // Inline style object\n if (\n \"style\" in props &&\n props.style != null &&\n typeof props.style === \"object\" &&\n !(props.style instanceof Reactive) &&\n isElementWithStyle(element)\n ) {\n applyStyles(element, props.style)\n delete props.style\n }\n\n // Classes object\n if (\n \"class\" in props &&\n props.class != null &&\n typeof props.class === \"object\" &&\n !(props.class instanceof Reactive)\n ) {\n applyClasses(element, props.class)\n delete props.class\n }\n\n for (const name_ in props) {\n const name = name_ as string & (keyof typeof props)\n // Event listener functions\n if (typeof props[name] === \"function\" && name.startsWith(\"on\")) {\n element.addEventListener(name.slice(2), props[name] as any)\n delete props[name]\n }\n }\n\n // The rest of the props are attributes\n applyAttributes(element, props as AttributesToApply<Name, NS>)\n\n return element\n}\n\nexport const Fragment =\n <Children extends BruhChild>\n (props: { children: Children }) => props.children\n\n//#endregion\n\n\nexport class BruhText extends HTMLElement {\n static hydrated: { readonly [tag: string]: ReadonlySet<Text> } = {}\n\n constructor() {\n super()\n\n const textNode = document.createTextNode(this.textContent!)\n\n const tag = this.getAttribute(\"tag\")\n if (tag) {\n const set = (BruhText.hydrated as { [tag: string]: Set<Text> })[tag] ??= new Set()\n set.add(textNode)\n }\n\n this.replaceWith(textNode)\n }\n}\n\ncustomElements.define(\"bruh-text\", BruhText)\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"bruh-text\": BruhText\n }\n}\ndeclare module \"html-info\" {\n interface HTMLTagToAttributes {\n \"bruh-text\": {\n \"tag\"?: string\n }\n }\n}\n"],"names":["node","first","last","element","props","name"],"mappings":"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"}
@@ -2,6 +2,7 @@ import { jsx, bruhChildrenToNodes } from '../browser.mjs';
2
2
  import { r } from '../reactive.mjs';
3
3
  import { spaceSeparated } from './utils.mjs';
4
4
  import { BruhCustomElementBase } from './custom-elements.mjs';
5
+ import { MemoMap } from './misc.mjs';
5
6
 
6
7
  const clamp = (min, x, max) => Math.min(Math.max(min, x), max);
7
8
  const getHeadingLevel = (heading) => parseInt(heading.localName[1]);
@@ -99,7 +100,6 @@ class BruhAsideTOC extends BruhCustomElementBase {
99
100
  constructor() {
100
101
  super();
101
102
  const headings = r(
102
- [this.bruh.attributes.headings, this.bruh.attributes["max-level"]],
103
103
  () => this.bruh.attributes.headings.value?.map((id) => this.ownerDocument.getElementById(id)).filter((e) => {
104
104
  if (!(e instanceof HTMLHeadingElement))
105
105
  return false;
@@ -108,7 +108,6 @@ class BruhAsideTOC extends BruhCustomElementBase {
108
108
  })
109
109
  );
110
110
  const container = r(
111
- [this.bruh.attributes.container],
112
111
  () => this.bruh.attributes.container.value ? this.ownerDocument.getElementById(this.bruh.attributes.container.value) ?? void 0 : void 0
113
112
  );
114
113
  const resizeOrScroll = r({ innerHeight, innerWidth, scrollY });
@@ -137,19 +136,21 @@ class BruhAsideTOC extends BruhCustomElementBase {
137
136
  }
138
137
  return new Map([...prominences].map(([heading, prominence]) => [heading, r(prominence)]));
139
138
  });
140
- this.#rendered = r([this.#prominences], () => {
139
+ this.#rendered = r(() => {
141
140
  const prominences = this.#prominences.value;
142
141
  if (!prominences)
143
142
  return;
144
- return /* @__PURE__ */ jsx("ol", { children: [...prominences].map(([heading, prominence]) => /* @__PURE__ */ jsx(
145
- "li",
146
- {
147
- class: `bruh-aside-toc--level-${getHeadingLevel(heading)}`,
148
- style: { "--prominence": prominence },
149
- children: /* @__PURE__ */ jsx("a", { href: `#${heading.id}`, children: heading.textContent })
150
- }
151
- )) });
152
- });
143
+ return /* @__PURE__ */ jsx("ol", { children: /* @__PURE__ */ jsx(MemoMap, { items: prominences, getKey: ([heading]) => heading, children: ([heading, prominence]) => {
144
+ /* @__PURE__ */ jsx(
145
+ "li",
146
+ {
147
+ class: `bruh-aside-toc--level-${getHeadingLevel(heading)}`,
148
+ style: { "--prominence": prominence },
149
+ children: /* @__PURE__ */ jsx("a", { href: `#${heading.id}`, children: heading.textContent })
150
+ }
151
+ );
152
+ } }) });
153
+ }, { memoKey: () => !this.#prominences.value });
153
154
  }
154
155
  mountedCallback() {
155
156
  const children = bruhChildrenToNodes([this.#rendered]);
@@ -1 +1 @@
1
- {"version":3,"file":"aside-toc.mjs","sources":["../../src/components/aside-toc/index.tsx"],"sourcesContent":["/** @jsxImportSource bruh/browser */\nimport { bruhChildrenToNodes } from \"bruh/browser\"\nimport { FunctionalReactive, r } from \"../../reactive/index.mts\"\nimport { spaceSeparated } from \"../utils.mts\"\nimport { BruhCustomElementBase } from \"../custom-elements.mts\"\n\nconst clamp = (min: number, x: number, max: number) =>\n Math.min(Math.max(min, x), max)\n\nconst getHeadingLevel = (heading: HTMLHeadingElement) =>\n parseInt(heading.localName[1])\n\ntype SectionMetrics = {\n contentTop: number,\n contentBottom: number,\n visibleContentTop: number,\n visibleContentBottom: number\n}\n\nconst getSectionMetrics = (\n headings: ReadonlyArray<HTMLHeadingElement>,\n container?: HTMLElement\n) => {\n const metrics = new Map<HTMLHeadingElement, SectionMetrics>()\n\n for (let i = 0; i < headings.length; i++) {\n const heading = headings[i]\n const currentLevel = getHeadingLevel(heading)\n\n let nextHeading: HTMLHeadingElement | undefined\n for (let j = i + 1; j < headings.length; j++) {\n const candidate = headings[j]\n const candidateLevel = getHeadingLevel(candidate)\n\n if (candidateLevel <= currentLevel) {\n nextHeading = candidate\n break\n }\n }\n\n const contentTop = heading.getBoundingClientRect().top\n const contentBottom =\n nextHeading?.getBoundingClientRect().top\n ?? (container ?? heading.parentElement)?.getBoundingClientRect().bottom\n ?? innerHeight\n\n const visibleContentTop = clamp(0, contentTop, innerHeight)\n const visibleContentBottom = clamp(0, contentBottom, innerHeight)\n\n metrics.set(heading, {\n contentTop,\n contentBottom,\n visibleContentTop,\n visibleContentBottom,\n })\n }\n\n return metrics\n}\n\nconst getProportionalPromience = (\n {\n contentTop,\n contentBottom,\n visibleContentTop,\n visibleContentBottom\n }: SectionMetrics\n) => {\n const contentHeight = contentBottom - contentTop\n const visibleContentHeight = visibleContentBottom - visibleContentTop\n\n if (visibleContentHeight === 0)\n return 0\n\n const visibleContentOverScreen = visibleContentHeight / innerHeight\n const proportionOfContentVisible = visibleContentHeight / contentHeight\n\n return Math.max(visibleContentOverScreen, proportionOfContentVisible)\n}\n\n/**\n * Cumulative Distribution Function over Kumaraswamy distribution (cheap and similar to beta)\n *\n * Corresponding PDF is `a * b * x ** (a - 1) * (1 - x ** a) ** (b - 1)`\n */\nconst kumaraswamyCDF = (\n a: number,\n b: number,\n /** Up to this point */\n x: number\n) => 1 - (1 - x ** a) ** b\n\n// We could have an e.g. 256 entry Float32Array of evenly split cached values\n// for expensive CDFs, but this one is very fast\n\n// I manually tuned these parameters to match what I thought looked accurate\n// The center of attention is ~22.5% of the way down the screen\nconst a = 1.4\nconst b = 3\n\nconst getProbabilisticProminence = (\n {\n visibleContentTop,\n visibleContentBottom\n }: SectionMetrics\n) =>\n kumaraswamyCDF(a, b, visibleContentBottom / innerHeight) -\n kumaraswamyCDF(a, b, visibleContentTop / innerHeight)\n\nconst getProminences = ({\n headings,\n probabilisticInfluence = 1/10\n}: {\n headings: ReadonlyArray<HTMLHeadingElement>,\n probabilisticInfluence?: number\n}) => {\n const metrics = getSectionMetrics(headings)\n\n const prominences = new Map<HTMLHeadingElement, number>()\n\n let i = 0\n for (const [heading, sectionMetrics] of metrics) {\n let prominence: number\n\n const proportionalProminence = probabilisticInfluence !== 1\n ? getProportionalPromience(sectionMetrics)\n : undefined\n\n const probabilisticProminence = probabilisticInfluence !== 0\n ? getProbabilisticProminence(sectionMetrics)\n : undefined\n\n if (probabilisticInfluence === 0)\n prominence = proportionalProminence!\n else if (probabilisticInfluence === 1)\n prominence = probabilisticProminence!\n else\n prominence = (\n proportionalProminence! ** (1 - probabilisticInfluence) *\n probabilisticProminence! ** probabilisticInfluence\n )\n\n prominences.set(heading, prominence)\n i++\n }\n\n return prominences\n}\n\n\ntype BruhAsideTOCAttributes = {\n \"headings\"?: ReadonlyArray<string>,\n \"container\"?: string,\n \"max-level\": 2 | 3 |4 | 5 | 6\n \"probabilistic-influence\"?: number\n}\n\nexport class BruhAsideTOC extends BruhCustomElementBase<BruhAsideTOCAttributes> {\n static observedAttributes = [\n \"headings\",\n \"container\",\n \"max-level\",\n \"probabilistic-influence\"\n ] as const\n\n static bruh = {\n parseAttributes: {\n headings: (s: string | null) => [...new Set(spaceSeparated(s))],\n\n container: (s: string | null) => s || undefined,\n\n \"max-level\": (s: string | null) => {\n const maxLevel = parseInt(s as string)\n return isNaN(maxLevel)\n ? 3\n : clamp(2, maxLevel, 6)\n },\n\n \"probabilistic-influence\": (s: string | null) => {\n const probabilisticInfluence = parseFloat(s as string)\n return isNaN(probabilisticInfluence)\n ? undefined\n : clamp(0, probabilisticInfluence, 1)\n }\n }\n }\n\n #prominences: FunctionalReactive<Map<HTMLHeadingElement, FunctionalReactive<number>> | undefined>\n #rendered\n\n constructor() {\n super()\n\n const headings = r([this.bruh.attributes.headings, this.bruh.attributes[\"max-level\"]], () =>\n this.bruh.attributes.headings.value\n ?.map(id => this.ownerDocument.getElementById(id))\n .filter((e): e is HTMLHeadingElement => {\n if (!(e instanceof HTMLHeadingElement))\n return false\n\n const level = getHeadingLevel(e)\n return level > 1 && level <= (this.bruh.attributes[\"max-level\"].value ?? 2)\n })\n )\n\n const container = r([this.bruh.attributes.container], () =>\n this.bruh.attributes.container.value\n ? this.ownerDocument.getElementById(this.bruh.attributes.container.value) ?? undefined\n : undefined\n )\n\n const resizeOrScroll = r({ innerHeight, innerWidth, scrollY })\n const onResizeOrScroll = () => {\n resizeOrScroll.value = { innerHeight, innerWidth, scrollY }\n }\n addEventListener(\"resize\", onResizeOrScroll, { passive: true })\n addEventListener(\"scroll\", onResizeOrScroll, { passive: true })\n\n this.#prominences = r([headings, container, this.bruh.attributes[\"probabilistic-influence\"], resizeOrScroll], () => {\n if (!headings.value?.length)\n return\n\n const prominences = getProminences({\n headings: headings.value,\n probabilisticInfluence: this.bruh.attributes[\"probabilistic-influence\"].value\n })\n\n const oldValue = this.#prominences.value\n if (oldValue) {\n const oldHeadings = new Set(oldValue.keys())\n const newHeadings = new Set(prominences.keys())\n const didChange =\n [...newHeadings].some(h => !oldHeadings.has(h)) ||\n [...oldHeadings].some(h => !newHeadings.has(h))\n\n if (!didChange) {\n for (const [heading, prominence] of prominences)\n oldValue.get(heading)!.value = prominence\n\n return oldValue\n }\n }\n\n return new Map([...prominences].map(([heading, prominence]) => [heading, r(prominence)]))\n })\n\n this.#rendered = r([this.#prominences], () => {\n const prominences = this.#prominences.value\n if (!prominences)\n return\n\n return (\n <ol>\n {[...prominences].map(([heading, prominence]) => (\n <li\n class={`bruh-aside-toc--level-${getHeadingLevel(heading)}`}\n style={{ \"--prominence\": prominence }}\n >\n <a href={`#${heading.id}`}>\n {heading.textContent}\n </a>\n </li>\n ))}\n </ol>\n )\n })\n }\n\n mountedCallback() {\n const children = bruhChildrenToNodes([this.#rendered])\n this.replaceChildren(...children)\n }\n}\n\ncustomElements.define(\"bruh-aside-toc\", BruhAsideTOC)\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"bruh-aside-toc\": BruhAsideTOC\n }\n}\ndeclare module \"html-info\" {\n interface HTMLTagToAttributes {\n \"bruh-aside-toc\": {\n /**\n * Space separated list of heading ids\n */\n \"headings\"?: ReadonlyArray<string>,\n /** Content container id */\n \"container\"?: string,\n \"max-level\"?: `${2 | 3 | 4 | 5 | 6}`\n }\n }\n}\ndeclare module \"csstype\" {\n interface PropertiesHyphen {\n \"--prominence\"?: number\n }\n}\n"],"names":["a","b"],"mappings":"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"}
1
+ {"version":3,"file":"aside-toc.mjs","sources":["../../src/components/aside-toc/index.tsx"],"sourcesContent":["/** @jsxImportSource bruh/browser */\nimport { bruhChildrenToNodes } from \"bruh/browser\"\nimport { Reactive, r } from \"../../reactive/index.mts\"\nimport { spaceSeparated } from \"../utils.mts\"\nimport { BruhCustomElementBase } from \"../custom-elements.mts\"\nimport { MemoMap } from \"../misc.mts\"\n\nconst clamp = (min: number, x: number, max: number) =>\n Math.min(Math.max(min, x), max)\n\nconst getHeadingLevel = (heading: HTMLHeadingElement) =>\n parseInt(heading.localName[1])\n\ntype SectionMetrics = {\n contentTop: number,\n contentBottom: number,\n visibleContentTop: number,\n visibleContentBottom: number\n}\n\nconst getSectionMetrics = (\n headings: ReadonlyArray<HTMLHeadingElement>,\n container?: HTMLElement\n) => {\n const metrics = new Map<HTMLHeadingElement, SectionMetrics>()\n\n for (let i = 0; i < headings.length; i++) {\n const heading = headings[i]\n const currentLevel = getHeadingLevel(heading)\n\n let nextHeading: HTMLHeadingElement | undefined\n for (let j = i + 1; j < headings.length; j++) {\n const candidate = headings[j]\n const candidateLevel = getHeadingLevel(candidate)\n\n if (candidateLevel <= currentLevel) {\n nextHeading = candidate\n break\n }\n }\n\n const contentTop = heading.getBoundingClientRect().top\n const contentBottom =\n nextHeading?.getBoundingClientRect().top\n ?? (container ?? heading.parentElement)?.getBoundingClientRect().bottom\n ?? innerHeight\n\n const visibleContentTop = clamp(0, contentTop, innerHeight)\n const visibleContentBottom = clamp(0, contentBottom, innerHeight)\n\n metrics.set(heading, {\n contentTop,\n contentBottom,\n visibleContentTop,\n visibleContentBottom,\n })\n }\n\n return metrics\n}\n\nconst getProportionalPromience = (\n {\n contentTop,\n contentBottom,\n visibleContentTop,\n visibleContentBottom\n }: SectionMetrics\n) => {\n const contentHeight = contentBottom - contentTop\n const visibleContentHeight = visibleContentBottom - visibleContentTop\n\n if (visibleContentHeight === 0)\n return 0\n\n const visibleContentOverScreen = visibleContentHeight / innerHeight\n const proportionOfContentVisible = visibleContentHeight / contentHeight\n\n return Math.max(visibleContentOverScreen, proportionOfContentVisible)\n}\n\n/**\n * Cumulative Distribution Function over Kumaraswamy distribution (cheap and similar to beta)\n *\n * Corresponding PDF is `a * b * x ** (a - 1) * (1 - x ** a) ** (b - 1)`\n */\nconst kumaraswamyCDF = (\n a: number,\n b: number,\n /** Up to this point */\n x: number\n) => 1 - (1 - x ** a) ** b\n\n// We could have an e.g. 256 entry Float32Array of evenly split cached values\n// for expensive CDFs, but this one is very fast\n\n// I manually tuned these parameters to match what I thought looked accurate\n// The center of attention is ~22.5% of the way down the screen\nconst a = 1.4\nconst b = 3\n\nconst getProbabilisticProminence = (\n {\n visibleContentTop,\n visibleContentBottom\n }: SectionMetrics\n) =>\n kumaraswamyCDF(a, b, visibleContentBottom / innerHeight) -\n kumaraswamyCDF(a, b, visibleContentTop / innerHeight)\n\nconst getProminences = ({\n headings,\n probabilisticInfluence = 1/10\n}: {\n headings: ReadonlyArray<HTMLHeadingElement>,\n probabilisticInfluence?: number\n}) => {\n const metrics = getSectionMetrics(headings)\n\n const prominences = new Map<HTMLHeadingElement, number>()\n\n let i = 0\n for (const [heading, sectionMetrics] of metrics) {\n let prominence: number\n\n const proportionalProminence = probabilisticInfluence !== 1\n ? getProportionalPromience(sectionMetrics)\n : undefined\n\n const probabilisticProminence = probabilisticInfluence !== 0\n ? getProbabilisticProminence(sectionMetrics)\n : undefined\n\n if (probabilisticInfluence === 0)\n prominence = proportionalProminence!\n else if (probabilisticInfluence === 1)\n prominence = probabilisticProminence!\n else\n prominence = (\n proportionalProminence! ** (1 - probabilisticInfluence) *\n probabilisticProminence! ** probabilisticInfluence\n )\n\n prominences.set(heading, prominence)\n i++\n }\n\n return prominences\n}\n\n\ntype BruhAsideTOCAttributes = {\n \"headings\"?: ReadonlyArray<string>,\n \"container\"?: string,\n \"max-level\": 2 | 3 |4 | 5 | 6\n \"probabilistic-influence\"?: number\n}\n\nexport class BruhAsideTOC extends BruhCustomElementBase<BruhAsideTOCAttributes> {\n static observedAttributes = [\n \"headings\",\n \"container\",\n \"max-level\",\n \"probabilistic-influence\"\n ] as const\n\n static bruh = {\n parseAttributes: {\n headings: (s: string | null) => [...new Set(spaceSeparated(s))],\n\n container: (s: string | null) => s || undefined,\n\n \"max-level\": (s: string | null) => {\n const maxLevel = parseInt(s as string)\n return isNaN(maxLevel)\n ? 3\n : clamp(2, maxLevel, 6)\n },\n\n \"probabilistic-influence\": (s: string | null) => {\n const probabilisticInfluence = parseFloat(s as string)\n return isNaN(probabilisticInfluence)\n ? undefined\n : clamp(0, probabilisticInfluence, 1)\n }\n }\n }\n\n #prominences: Reactive<Map<HTMLHeadingElement, Reactive<number>> | undefined>\n #rendered\n\n constructor() {\n super()\n\n const headings = r(() =>\n this.bruh.attributes.headings.value\n ?.map(id => this.ownerDocument.getElementById(id))\n .filter((e): e is HTMLHeadingElement => {\n if (!(e instanceof HTMLHeadingElement))\n return false\n\n const level = getHeadingLevel(e)\n return level > 1 && level <= (this.bruh.attributes[\"max-level\"].value ?? 2)\n })\n )\n\n const container = r(() =>\n this.bruh.attributes.container.value\n ? this.ownerDocument.getElementById(this.bruh.attributes.container.value) ?? undefined\n : undefined\n )\n\n const resizeOrScroll = r({ innerHeight, innerWidth, scrollY })\n const onResizeOrScroll = () => {\n resizeOrScroll.value = { innerHeight, innerWidth, scrollY }\n }\n addEventListener(\"resize\", onResizeOrScroll, { passive: true })\n addEventListener(\"scroll\", onResizeOrScroll, { passive: true })\n\n this.#prominences = r([headings, container, this.bruh.attributes[\"probabilistic-influence\"], resizeOrScroll], () => {\n if (!headings.value?.length)\n return\n\n const prominences = getProminences({\n headings: headings.value,\n probabilisticInfluence: this.bruh.attributes[\"probabilistic-influence\"].value\n })\n\n const oldValue = this.#prominences.value\n if (oldValue) {\n const oldHeadings = new Set(oldValue.keys())\n const newHeadings = new Set(prominences.keys())\n const didChange =\n [...newHeadings].some(h => !oldHeadings.has(h)) ||\n [...oldHeadings].some(h => !newHeadings.has(h))\n\n if (!didChange) {\n for (const [heading, prominence] of prominences)\n oldValue.get(heading)!.value = prominence\n\n return oldValue\n }\n }\n\n return new Map([...prominences].map(([heading, prominence]) => [heading, r(prominence)]))\n })\n\n this.#rendered = r(() => {\n const prominences = this.#prominences.value\n if (!prominences)\n return\n\n return (\n <ol>\n <MemoMap items={prominences} getKey={([heading]) => heading}>\n {([heading, prominence]) => {\n <li\n class={`bruh-aside-toc--level-${getHeadingLevel(heading)}`}\n style={{ \"--prominence\": prominence }}\n >\n <a href={`#${heading.id}`}>\n {heading.textContent}\n </a>\n </li>\n }}\n </MemoMap>\n </ol>\n )\n }, { memoKey: () => !this.#prominences.value })\n }\n\n mountedCallback() {\n const children = bruhChildrenToNodes([this.#rendered])\n this.replaceChildren(...children)\n }\n}\n\ncustomElements.define(\"bruh-aside-toc\", BruhAsideTOC)\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"bruh-aside-toc\": BruhAsideTOC\n }\n}\ndeclare module \"html-info\" {\n interface HTMLTagToAttributes {\n \"bruh-aside-toc\": {\n /**\n * Space separated list of heading ids\n */\n \"headings\"?: ReadonlyArray<string>,\n /** Content container id */\n \"container\"?: string,\n \"max-level\"?: `${2 | 3 | 4 | 5 | 6}`\n }\n }\n}\ndeclare module \"csstype\" {\n interface PropertiesHyphen {\n \"--prominence\"?: number\n }\n}\n"],"names":["a","b"],"mappings":"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"}
@@ -137,7 +137,6 @@ class BruhDateTime extends BruhCustomElementBase {
137
137
  constructor() {
138
138
  super();
139
139
  this.#locales = r(
140
- [this.bruh.attributes.locales, userLanguages],
141
140
  () => parseLocales([
142
141
  ...this.bruh.attributes.locales.value ?? [],
143
142
  ...userLanguages.value
@@ -152,7 +151,6 @@ class BruhDateTime extends BruhCustomElementBase {
152
151
  () => mapObject(optionToReactiveAttribute, ([option, attribute]) => [option, attribute.value || void 0])
153
152
  );
154
153
  this.#formatter = r(
155
- [this.#locales, this.#options],
156
154
  () => attempt(() => new Intl.DateTimeFormat(this.#locales.value, this.#options.value)) ?? new Intl.DateTimeFormat(this.#locales.value)
157
155
  );
158
156
  const dateToFormat = this.bruh.attributes.date;
@@ -198,7 +196,7 @@ class BruhDateTime extends BruhCustomElementBase {
198
196
  }
199
197
  });
200
198
  };
201
- this.#formatted = r([this.#formatter, dateToFormat, rangeEndDateToFormat], () => {
199
+ this.#formatted = r(() => {
202
200
  if (!dateToFormat.value)
203
201
  return;
204
202
  const formatter = this.#formatter.value;
@@ -1 +1 @@
1
- {"version":3,"file":"date-time.mjs","sources":["../../../src/components/intl/date-time.tsx"],"sourcesContent":["/** @jsxImportSource bruh/browser */\nimport { bruhChildrenToNodes, type BruhProps } from \"bruh/browser\"\nimport { r } from \"../../reactive/index.mts\"\nimport { attempt, mapObject } from \"../../utils/index.mts\"\nimport { spaceSeparated } from \"../utils.mts\"\nimport { BruhCustomElementBase } from \"../custom-elements.mts\"\nimport { inferDirection, parseLocales, userLanguages } from \"./utils.mts\"\n\n// todo: reactive updating times / responding to current time using found setTimeout or requestAnimationFrame\n\n/**\n * In minutes from UTC/GMT, same as `new Date().getTimezoneOffset()`, but for any time zone\n *\n * `undefined` if unknown\n */\nexport const getTimeZoneOffset = (timeZone?: string) => {\n if (timeZone === undefined)\n return new Date().getTimezoneOffset()\n\n const longOffset = new Intl.DateTimeFormat(\"en\", {\n timeZone,\n timeZoneName: \"longOffset\"\n })\n .formatToParts(new Date())\n .find(part => part.type === \"timeZoneName\")?.value\n\n if (!longOffset)\n return\n\n if (longOffset === \"GMT\" || longOffset === \"UTC\")\n return 0\n\n const [hoursUnparsed, minutesUnparsed] = longOffset.replace(/^(GMT|UTC)/, \"\").split(\":\")\n const hoursParsed = parseInt(hoursUnparsed)\n const minutesParsed =\n minutesUnparsed !== undefined\n ? Math.sign(hoursParsed) * parseInt(minutesUnparsed)\n : 0\n\n const inMinutes = -1 * (hoursParsed * 60 + minutesParsed)\n if (isFinite(inMinutes))\n return inMinutes\n}\n\nexport const currentTimeZone = () =>\n new Intl.DateTimeFormat().resolvedOptions().timeZone\n\n/**\n * Makes a date that has a UTC time set to the input date's local time in the given time zone\n */\nexport const localDateInUTC = (date: Date | number, timeZone: string) => {\n const offset = getTimeZoneOffset(timeZone)\n if (offset === undefined)\n return undefined\n\n return new Date((date as number) - offset * 60 * 1_000)\n}\n\nexport const hideRedundantOptions = (\n originalFormatter: Intl.DateTimeFormat,\n {\n date,\n endDate,\n now = new Date()\n }: {\n date: Date,\n endDate?: Date,\n now?: Date\n }\n) => {\n const resolvedOptions = originalFormatter.resolvedOptions() as Intl.ResolvedDateTimeFormatOptions & Intl.DateTimeFormatOptions\n const minimizedOptions = { ...resolvedOptions }\n\n if (resolvedOptions.timeZone === currentTimeZone() || getTimeZoneOffset(resolvedOptions.timeZone) === getTimeZoneOffset())\n delete minimizedOptions.timeZoneName\n\n // https://tc39.es/ecma402/#table-datetimeformat-tolocaltime-record\n if (resolvedOptions.calendar === \"gregory\") {\n const timeZonedDate = localDateInUTC(date, resolvedOptions.timeZone)\n if (timeZonedDate !== undefined) {\n const dateYear = timeZonedDate.getUTCFullYear()\n const dateMonth = timeZonedDate.getUTCMonth()\n const dateDate = timeZonedDate.getUTCDate()\n\n const timeZonedEndDate =\n endDate !== undefined\n ? localDateInUTC(endDate, resolvedOptions.timeZone)\n : undefined\n const missingEndDate = timeZonedEndDate === undefined\n if (missingEndDate === (endDate === undefined)) {\n const endDateYear = timeZonedEndDate?.getUTCFullYear()\n const endDateMonth = timeZonedEndDate?.getUTCMonth()\n const endDateDate = timeZonedEndDate?.getUTCDate()\n\n const currentYear = now.getFullYear()\n const currentMonth = now.getMonth()\n const currentDate = now.getDate()\n\n const dateSameEra = dateYear < 1 === currentYear < 1\n const endDateSameEra = missingEndDate || (endDateYear! < 1 === currentYear < 1)\n if (dateSameEra && endDateSameEra) {\n delete minimizedOptions.era\n\n const dateSameYear = dateYear === currentYear\n const endDateSameYear = missingEndDate || (endDateYear! === currentYear)\n if (dateSameYear && endDateSameYear) {\n delete minimizedOptions.year\n\n const dateSameMonthAndDate = dateMonth === currentMonth && dateDate === currentDate\n const endDateSameMonthAndDate = missingEndDate || (endDateMonth! === currentMonth && endDateDate! === currentDate)\n if (dateSameMonthAndDate && endDateSameMonthAndDate) {\n delete minimizedOptions.month\n delete minimizedOptions.day\n delete minimizedOptions.weekday\n }\n }\n }\n }\n }\n }\n\n return new Intl.DateTimeFormat(resolvedOptions.locale, minimizedOptions)\n}\n\nexport const parseDate = (unparsed?: string | null) => {\n if (unparsed == undefined)\n return\n\n if (unparsed === \"\")\n return { type: \"now\" } as const\n\n const date = new Date(unparsed)\n if (isFinite(date as any as number))\n return { type: \"date\", date } as const\n\n const numberThenDate = new Date(Number(unparsed))\n if (isFinite(numberThenDate as any as number))\n return { type: \"date\", date: numberThenDate } as const\n\n return { type: \"unparsed\", unparsed } as const\n}\n\nexport type ParsedDate = ReturnType<typeof parseDate>\n\nconst optionToAttribute = {\n // locale options\n \"localeMatcher\": \"locale-matcher\",\n \"calendar\": \"calendar\",\n \"numberingSystem\": \"numbering-system\",\n \"hour12\": \"hour12\",\n \"hourCycle\": \"hour-cycle\",\n \"timeZone\": \"time-zone\",\n // style options\n \"weekday\": \"weekday\",\n \"era\": \"era\",\n \"year\": \"year\",\n \"month\": \"month\",\n \"day\": \"day\",\n \"dayPeriod\": \"day-period\",\n \"hour\": \"hour\",\n \"minute\": \"minute\",\n \"second\": \"second\",\n \"fractionalSecondDigits\": \"fractional-second-digits\",\n \"timeZoneName\": \"time-zone-name\",\n \"formatMatcher\": \"format-matcher\",\n // style shortcuts\n \"dateStyle\": \"date-style\",\n \"timeStyle\": \"time-style\"\n} as const\n\ntype BruhDateTimeAttributes = {\n \"date\"?: ParsedDate,\n \"end-date\"?: ParsedDate,\n \"locales\"?: ReadonlyArray<Intl.UnicodeBCP47LocaleIdentifier>,\n \"hide-redundant-options\"?: boolean,\n \"locale-matcher\"?: Intl.DateTimeFormatOptions[\"localeMatcher\"],\n \"calendar\"?: Intl.DateTimeFormatOptions[\"calendar\"],\n \"numbering-system\"?: Intl.DateTimeFormatOptions[\"numberingSystem\"],\n \"hour12\"?: Intl.DateTimeFormatOptions[\"hour12\"],\n \"hour-cycle\"?: Intl.DateTimeFormatOptions[\"hourCycle\"],\n \"time-zone\"?: Intl.DateTimeFormatOptions[\"timeZone\"],\n \"weekday\"?: Intl.DateTimeFormatOptions[\"weekday\"],\n \"era\"?: Intl.DateTimeFormatOptions[\"era\"],\n \"year\"?: Intl.DateTimeFormatOptions[\"year\"],\n \"month\"?: Intl.DateTimeFormatOptions[\"month\"],\n \"day\"?: Intl.DateTimeFormatOptions[\"day\"],\n \"day-period\"?: Intl.DateTimeFormatOptions[\"dayPeriod\"],\n \"hour\"?: Intl.DateTimeFormatOptions[\"hour\"],\n \"minute\"?: Intl.DateTimeFormatOptions[\"minute\"],\n \"second\"?: Intl.DateTimeFormatOptions[\"second\"],\n \"fractional-second-digits\"?: Intl.DateTimeFormatOptions[\"fractionalSecondDigits\"],\n \"time-zone-name\"?: Intl.DateTimeFormatOptions[\"timeZoneName\"],\n \"format-matcher\"?: Intl.DateTimeFormatOptions[\"formatMatcher\"],\n \"date-style\"?: Intl.DateTimeFormatOptions[\"dateStyle\"],\n \"time-style\"?: Intl.DateTimeFormatOptions[\"timeStyle\"]\n}\n\nexport class BruhDateTime extends BruhCustomElementBase<BruhDateTimeAttributes> {\n static observedAttributes = [\n \"date\",\n \"end-date\",\n \"locales\",\n \"hide-redundant-options\",\n ...Object.values(optionToAttribute)\n ]\n\n static bruh = {\n parseAttributes: {\n date: parseDate,\n \"end-date\": parseDate,\n locales: spaceSeparated,\n \"hide-redundant-options\": (v?: string | null) => v != undefined\n }\n }\n\n #locales\n #options\n #formatter\n #formatted\n\n constructor() {\n super()\n\n this.#locales = r([this.bruh.attributes.locales, userLanguages], () =>\n parseLocales([\n ...this.bruh.attributes.locales.value ?? [],\n ...userLanguages.value\n ])\n )\n\n const optionToReactiveAttribute = mapObject(optionToAttribute,\n ([option, attribute]) => [option, this.bruh.attributes[attribute]]\n )\n this.#options = r(Object.values(optionToReactiveAttribute), () =>\n mapObject(optionToReactiveAttribute, ([option, attribute]) => [option, attribute.value || undefined]) as Partial<Intl.DateTimeFormatOptions>\n )\n\n this.#formatter = r([this.#locales, this.#options], () =>\n attempt(() => new Intl.DateTimeFormat(this.#locales.value, this.#options.value))\n ?? new Intl.DateTimeFormat(this.#locales.value)\n )\n\n const dateToFormat = this.bruh.attributes.date\n const rangeEndDateToFormat = this.bruh.attributes[\"end-date\"]\n\n const renderParts = (parts: ReadonlyArray<Intl.DateTimeFormatPart>) =>\n parts.map(part =>\n <span class={`bruh-date-time-part bruh-date-time-part--${part.type}`}>{part.value}</span> as HTMLSpanElement\n )\n\n const renderSingle = (\n date: NonNullable<ParsedDate>,\n attributes?: BruhProps<\"time\">\n ) => {\n if (date.type === \"unparsed\")\n return <time {...attributes} datetime={date.unparsed}>{date.unparsed}</time> as HTMLTimeElement\n\n const value =\n date.type === \"now\"\n ? new Date()\n : date.date\n\n const formatter =\n this.bruh.attributes[\"hide-redundant-options\"].value\n ? hideRedundantOptions(this.#formatter.value, { date: value })\n : this.#formatter.value\n\n const rendered = renderParts(formatter.formatToParts(value))\n return <time {...attributes} datetime={value.toISOString()}>{rendered}</time> as HTMLTimeElement\n }\n\n const renderRange = (start: NonNullable<ParsedDate>, end: NonNullable<ParsedDate>) => {\n const canRenderRangeDirectly =\n \"formatRangeToParts\" in this.#formatter.value\n && start.type !== \"unparsed\"\n && end.type !== \"unparsed\"\n if (!canRenderRangeDirectly)\n return [\n renderSingle(start, { class: \"bruh-date-time-source bruh-date-time-source--startRange\" }),\n <span class=\"bruh-date-time-source bruh-date-time-source--shared\">\n <span class=\"bruh-date-time-part bruh-date-time-part--literal\"> – </span>\n </span> as HTMLSpanElement,\n renderSingle(end, { class: \"bruh-date-time-source bruh-date-time-source--endRange\" })\n ]\n\n const startValue =\n start.type === \"now\"\n ? new Date()\n : start.date\n const endValue =\n end.type === \"now\"\n ? new Date()\n : end.date\n\n const formatter =\n this.bruh.attributes[\"hide-redundant-options\"].value\n ? hideRedundantOptions(this.#formatter.value, { date: startValue, endDate: endValue })\n : this.#formatter.value\n\n const parts = formatter.formatRangeToParts(startValue, endValue)\n const bySource = parts.reduce<Intl.DateTimeRangeFormatPart[][]>((bySource, part, i) => {\n if (!i || parts[i - 1].source !== part.source)\n bySource.push([])\n bySource[bySource.length - 1].push(part)\n return bySource\n }, [])\n return bySource.map(parts => {\n const source = parts[0].source\n const className = `bruh-date-time-source bruh-date-time-source--${source}`\n const rendered = renderParts(parts)\n if (source === \"startRange\" || source === \"endRange\" || (source === \"shared\" && bySource.length === 1)) {\n const dateTime =\n source === \"startRange\"\n ? startValue\n : endValue\n return <time class={className} datetime={dateTime.toISOString()}>{rendered}</time> as HTMLTimeElement\n }\n else {\n return <span class={className}>{rendered}</span> as HTMLSpanElement\n }\n })\n }\n\n this.#formatted = r([this.#formatter, dateToFormat, rangeEndDateToFormat], () => {\n if (!dateToFormat.value)\n return\n\n const formatter = this.#formatter.value\n const { locale } = formatter.resolvedOptions()\n const direction = inferDirection(locale)\n\n const result =\n rangeEndDateToFormat.value\n ? renderRange(dateToFormat.value, rangeEndDateToFormat.value)\n : renderSingle(dateToFormat.value)\n\n return <bdi lang={locale} dir={direction}>{result}</bdi> as HTMLElement\n })\n }\n\n mountedCallback() {\n const children = bruhChildrenToNodes([this.#formatted])\n this.replaceChildren(...children)\n }\n}\n\ncustomElements.define(\"bruh-date-time\", BruhDateTime)\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"bruh-date-time\": BruhDateTime\n }\n}\ndeclare module \"html-info\" {\n interface HTMLTagToAttributes {\n \"bruh-date-time\": {\n \"date\"?: string\n \"end-date\"?: string\n /**\n * Space separated list of locales\n */\n \"locales\"?: string,\n \"hide-redundant-options\"?: boolean,\n \"locale-matcher\"?: Intl.DateTimeFormatOptions[\"localeMatcher\"],\n \"calendar\"?: Intl.DateTimeFormatOptions[\"calendar\"],\n \"numbering-system\"?: Intl.DateTimeFormatOptions[\"numberingSystem\"],\n \"hour12\"?: Intl.DateTimeFormatOptions[\"hour12\"],\n \"hour-cycle\"?: Intl.DateTimeFormatOptions[\"hourCycle\"],\n \"time-zone\"?: Intl.DateTimeFormatOptions[\"timeZone\"],\n \"weekday\"?: Intl.DateTimeFormatOptions[\"weekday\"],\n \"era\"?: Intl.DateTimeFormatOptions[\"era\"],\n \"year\"?: Intl.DateTimeFormatOptions[\"year\"],\n \"month\"?: Intl.DateTimeFormatOptions[\"month\"],\n \"day\"?: Intl.DateTimeFormatOptions[\"day\"],\n \"day-period\"?: Intl.DateTimeFormatOptions[\"dayPeriod\"],\n \"hour\"?: Intl.DateTimeFormatOptions[\"hour\"],\n \"minute\"?: Intl.DateTimeFormatOptions[\"minute\"],\n \"second\"?: Intl.DateTimeFormatOptions[\"second\"],\n \"fractional-second-digits\"?: Intl.DateTimeFormatOptions[\"fractionalSecondDigits\"] | `${Intl.DateTimeFormatOptions[\"fractionalSecondDigits\"]}`,\n \"time-zone-name\"?: Intl.DateTimeFormatOptions[\"timeZoneName\"],\n \"format-matcher\"?: Intl.DateTimeFormatOptions[\"formatMatcher\"],\n \"date-style\"?: Intl.DateTimeFormatOptions[\"dateStyle\"],\n \"time-style\"?: Intl.DateTimeFormatOptions[\"timeStyle\"]\n }\n }\n}\n"],"names":["bySource","parts"],"mappings":"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"}
1
+ {"version":3,"file":"date-time.mjs","sources":["../../../src/components/intl/date-time.tsx"],"sourcesContent":["/** @jsxImportSource bruh/browser */\nimport { bruhChildrenToNodes, type BruhProps } from \"bruh/browser\"\nimport { r } from \"../../reactive/index.mts\"\nimport { attempt, mapObject } from \"../../utils/index.mts\"\nimport { spaceSeparated } from \"../utils.mts\"\nimport { BruhCustomElementBase } from \"../custom-elements.mts\"\nimport { inferDirection, parseLocales, userLanguages } from \"./utils.mts\"\n\n// todo: reactive updating times / responding to current time using found setTimeout or requestAnimationFrame\n\n/**\n * In minutes from UTC/GMT, same as `new Date().getTimezoneOffset()`, but for any time zone\n *\n * `undefined` if unknown\n */\nexport const getTimeZoneOffset = (timeZone?: string) => {\n if (timeZone === undefined)\n return new Date().getTimezoneOffset()\n\n const longOffset = new Intl.DateTimeFormat(\"en\", {\n timeZone,\n timeZoneName: \"longOffset\"\n })\n .formatToParts(new Date())\n .find(part => part.type === \"timeZoneName\")?.value\n\n if (!longOffset)\n return\n\n if (longOffset === \"GMT\" || longOffset === \"UTC\")\n return 0\n\n const [hoursUnparsed, minutesUnparsed] = longOffset.replace(/^(GMT|UTC)/, \"\").split(\":\")\n const hoursParsed = parseInt(hoursUnparsed)\n const minutesParsed =\n minutesUnparsed !== undefined\n ? Math.sign(hoursParsed) * parseInt(minutesUnparsed)\n : 0\n\n const inMinutes = -1 * (hoursParsed * 60 + minutesParsed)\n if (isFinite(inMinutes))\n return inMinutes\n}\n\nexport const currentTimeZone = () =>\n new Intl.DateTimeFormat().resolvedOptions().timeZone\n\n/**\n * Makes a date that has a UTC time set to the input date's local time in the given time zone\n */\nexport const localDateInUTC = (date: Date | number, timeZone: string) => {\n const offset = getTimeZoneOffset(timeZone)\n if (offset === undefined)\n return undefined\n\n return new Date((date as number) - offset * 60 * 1_000)\n}\n\nexport const hideRedundantOptions = (\n originalFormatter: Intl.DateTimeFormat,\n {\n date,\n endDate,\n now = new Date()\n }: {\n date: Date,\n endDate?: Date,\n now?: Date\n }\n) => {\n const resolvedOptions = originalFormatter.resolvedOptions() as Intl.ResolvedDateTimeFormatOptions & Intl.DateTimeFormatOptions\n const minimizedOptions = { ...resolvedOptions }\n\n if (resolvedOptions.timeZone === currentTimeZone() || getTimeZoneOffset(resolvedOptions.timeZone) === getTimeZoneOffset())\n delete minimizedOptions.timeZoneName\n\n // https://tc39.es/ecma402/#table-datetimeformat-tolocaltime-record\n if (resolvedOptions.calendar === \"gregory\") {\n const timeZonedDate = localDateInUTC(date, resolvedOptions.timeZone)\n if (timeZonedDate !== undefined) {\n const dateYear = timeZonedDate.getUTCFullYear()\n const dateMonth = timeZonedDate.getUTCMonth()\n const dateDate = timeZonedDate.getUTCDate()\n\n const timeZonedEndDate =\n endDate !== undefined\n ? localDateInUTC(endDate, resolvedOptions.timeZone)\n : undefined\n const missingEndDate = timeZonedEndDate === undefined\n if (missingEndDate === (endDate === undefined)) {\n const endDateYear = timeZonedEndDate?.getUTCFullYear()\n const endDateMonth = timeZonedEndDate?.getUTCMonth()\n const endDateDate = timeZonedEndDate?.getUTCDate()\n\n const currentYear = now.getFullYear()\n const currentMonth = now.getMonth()\n const currentDate = now.getDate()\n\n const dateSameEra = dateYear < 1 === currentYear < 1\n const endDateSameEra = missingEndDate || (endDateYear! < 1 === currentYear < 1)\n if (dateSameEra && endDateSameEra) {\n delete minimizedOptions.era\n\n const dateSameYear = dateYear === currentYear\n const endDateSameYear = missingEndDate || (endDateYear! === currentYear)\n if (dateSameYear && endDateSameYear) {\n delete minimizedOptions.year\n\n const dateSameMonthAndDate = dateMonth === currentMonth && dateDate === currentDate\n const endDateSameMonthAndDate = missingEndDate || (endDateMonth! === currentMonth && endDateDate! === currentDate)\n if (dateSameMonthAndDate && endDateSameMonthAndDate) {\n delete minimizedOptions.month\n delete minimizedOptions.day\n delete minimizedOptions.weekday\n }\n }\n }\n }\n }\n }\n\n return new Intl.DateTimeFormat(resolvedOptions.locale, minimizedOptions)\n}\n\nexport const parseDate = (unparsed?: string | null) => {\n if (unparsed == undefined)\n return\n\n if (unparsed === \"\")\n return { type: \"now\" } as const\n\n const date = new Date(unparsed)\n if (isFinite(date as any as number))\n return { type: \"date\", date } as const\n\n const numberThenDate = new Date(Number(unparsed))\n if (isFinite(numberThenDate as any as number))\n return { type: \"date\", date: numberThenDate } as const\n\n return { type: \"unparsed\", unparsed } as const\n}\n\nexport type ParsedDate = ReturnType<typeof parseDate>\n\nconst optionToAttribute = {\n // locale options\n \"localeMatcher\": \"locale-matcher\",\n \"calendar\": \"calendar\",\n \"numberingSystem\": \"numbering-system\",\n \"hour12\": \"hour12\",\n \"hourCycle\": \"hour-cycle\",\n \"timeZone\": \"time-zone\",\n // style options\n \"weekday\": \"weekday\",\n \"era\": \"era\",\n \"year\": \"year\",\n \"month\": \"month\",\n \"day\": \"day\",\n \"dayPeriod\": \"day-period\",\n \"hour\": \"hour\",\n \"minute\": \"minute\",\n \"second\": \"second\",\n \"fractionalSecondDigits\": \"fractional-second-digits\",\n \"timeZoneName\": \"time-zone-name\",\n \"formatMatcher\": \"format-matcher\",\n // style shortcuts\n \"dateStyle\": \"date-style\",\n \"timeStyle\": \"time-style\"\n} as const\n\ntype BruhDateTimeAttributes = {\n \"date\"?: ParsedDate,\n \"end-date\"?: ParsedDate,\n \"locales\"?: ReadonlyArray<Intl.UnicodeBCP47LocaleIdentifier>,\n \"hide-redundant-options\"?: boolean,\n \"locale-matcher\"?: Intl.DateTimeFormatOptions[\"localeMatcher\"],\n \"calendar\"?: Intl.DateTimeFormatOptions[\"calendar\"],\n \"numbering-system\"?: Intl.DateTimeFormatOptions[\"numberingSystem\"],\n \"hour12\"?: Intl.DateTimeFormatOptions[\"hour12\"],\n \"hour-cycle\"?: Intl.DateTimeFormatOptions[\"hourCycle\"],\n \"time-zone\"?: Intl.DateTimeFormatOptions[\"timeZone\"],\n \"weekday\"?: Intl.DateTimeFormatOptions[\"weekday\"],\n \"era\"?: Intl.DateTimeFormatOptions[\"era\"],\n \"year\"?: Intl.DateTimeFormatOptions[\"year\"],\n \"month\"?: Intl.DateTimeFormatOptions[\"month\"],\n \"day\"?: Intl.DateTimeFormatOptions[\"day\"],\n \"day-period\"?: Intl.DateTimeFormatOptions[\"dayPeriod\"],\n \"hour\"?: Intl.DateTimeFormatOptions[\"hour\"],\n \"minute\"?: Intl.DateTimeFormatOptions[\"minute\"],\n \"second\"?: Intl.DateTimeFormatOptions[\"second\"],\n \"fractional-second-digits\"?: Intl.DateTimeFormatOptions[\"fractionalSecondDigits\"],\n \"time-zone-name\"?: Intl.DateTimeFormatOptions[\"timeZoneName\"],\n \"format-matcher\"?: Intl.DateTimeFormatOptions[\"formatMatcher\"],\n \"date-style\"?: Intl.DateTimeFormatOptions[\"dateStyle\"],\n \"time-style\"?: Intl.DateTimeFormatOptions[\"timeStyle\"]\n}\n\nexport class BruhDateTime extends BruhCustomElementBase<BruhDateTimeAttributes> {\n static observedAttributes = [\n \"date\",\n \"end-date\",\n \"locales\",\n \"hide-redundant-options\",\n ...Object.values(optionToAttribute)\n ]\n\n static bruh = {\n parseAttributes: {\n date: parseDate,\n \"end-date\": parseDate,\n locales: spaceSeparated,\n \"hide-redundant-options\": (v?: string | null) => v != undefined\n }\n }\n\n #locales\n #options\n #formatter\n #formatted\n\n constructor() {\n super()\n\n this.#locales = r(() =>\n parseLocales([\n ...this.bruh.attributes.locales.value ?? [],\n ...userLanguages.value\n ])\n )\n\n const optionToReactiveAttribute = mapObject(optionToAttribute,\n ([option, attribute]) => [option, this.bruh.attributes[attribute]]\n )\n this.#options = r(Object.values(optionToReactiveAttribute), () =>\n mapObject(optionToReactiveAttribute, ([option, attribute]) => [option, attribute.value || undefined]) as Partial<Intl.DateTimeFormatOptions>\n )\n\n this.#formatter = r(() =>\n attempt(() => new Intl.DateTimeFormat(this.#locales.value, this.#options.value))\n ?? new Intl.DateTimeFormat(this.#locales.value)\n )\n\n const dateToFormat = this.bruh.attributes.date\n const rangeEndDateToFormat = this.bruh.attributes[\"end-date\"]\n\n const renderParts = (parts: ReadonlyArray<Intl.DateTimeFormatPart>) =>\n parts.map(part =>\n <span class={`bruh-date-time-part bruh-date-time-part--${part.type}`}>{part.value}</span> as HTMLSpanElement\n )\n\n const renderSingle = (\n date: NonNullable<ParsedDate>,\n attributes?: BruhProps<\"time\">\n ) => {\n if (date.type === \"unparsed\")\n return <time {...attributes} datetime={date.unparsed}>{date.unparsed}</time> as HTMLTimeElement\n\n const value =\n date.type === \"now\"\n ? new Date()\n : date.date\n\n const formatter =\n this.bruh.attributes[\"hide-redundant-options\"].value\n ? hideRedundantOptions(this.#formatter.value, { date: value })\n : this.#formatter.value\n\n const rendered = renderParts(formatter.formatToParts(value))\n return <time {...attributes} datetime={value.toISOString()}>{rendered}</time> as HTMLTimeElement\n }\n\n const renderRange = (start: NonNullable<ParsedDate>, end: NonNullable<ParsedDate>) => {\n const canRenderRangeDirectly =\n \"formatRangeToParts\" in this.#formatter.value\n && start.type !== \"unparsed\"\n && end.type !== \"unparsed\"\n if (!canRenderRangeDirectly)\n return [\n renderSingle(start, { class: \"bruh-date-time-source bruh-date-time-source--startRange\" }),\n <span class=\"bruh-date-time-source bruh-date-time-source--shared\">\n <span class=\"bruh-date-time-part bruh-date-time-part--literal\"> – </span>\n </span> as HTMLSpanElement,\n renderSingle(end, { class: \"bruh-date-time-source bruh-date-time-source--endRange\" })\n ]\n\n const startValue =\n start.type === \"now\"\n ? new Date()\n : start.date\n const endValue =\n end.type === \"now\"\n ? new Date()\n : end.date\n\n const formatter =\n this.bruh.attributes[\"hide-redundant-options\"].value\n ? hideRedundantOptions(this.#formatter.value, { date: startValue, endDate: endValue })\n : this.#formatter.value\n\n const parts = formatter.formatRangeToParts(startValue, endValue)\n const bySource = parts.reduce<Intl.DateTimeRangeFormatPart[][]>((bySource, part, i) => {\n if (!i || parts[i - 1].source !== part.source)\n bySource.push([])\n bySource[bySource.length - 1].push(part)\n return bySource\n }, [])\n return bySource.map(parts => {\n const source = parts[0].source\n const className = `bruh-date-time-source bruh-date-time-source--${source}`\n const rendered = renderParts(parts)\n if (source === \"startRange\" || source === \"endRange\" || (source === \"shared\" && bySource.length === 1)) {\n const dateTime =\n source === \"startRange\"\n ? startValue\n : endValue\n return <time class={className} datetime={dateTime.toISOString()}>{rendered}</time> as HTMLTimeElement\n }\n else {\n return <span class={className}>{rendered}</span> as HTMLSpanElement\n }\n })\n }\n\n this.#formatted = r(() => {\n if (!dateToFormat.value)\n return\n\n const formatter = this.#formatter.value\n const { locale } = formatter.resolvedOptions()\n const direction = inferDirection(locale)\n\n const result =\n rangeEndDateToFormat.value\n ? renderRange(dateToFormat.value, rangeEndDateToFormat.value)\n : renderSingle(dateToFormat.value)\n\n return <bdi lang={locale} dir={direction}>{result}</bdi> as HTMLElement\n })\n }\n\n mountedCallback() {\n const children = bruhChildrenToNodes([this.#formatted])\n this.replaceChildren(...children)\n }\n}\n\ncustomElements.define(\"bruh-date-time\", BruhDateTime)\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"bruh-date-time\": BruhDateTime\n }\n}\ndeclare module \"html-info\" {\n interface HTMLTagToAttributes {\n \"bruh-date-time\": {\n \"date\"?: string\n \"end-date\"?: string\n /**\n * Space separated list of locales\n */\n \"locales\"?: string,\n \"hide-redundant-options\"?: boolean,\n \"locale-matcher\"?: Intl.DateTimeFormatOptions[\"localeMatcher\"],\n \"calendar\"?: Intl.DateTimeFormatOptions[\"calendar\"],\n \"numbering-system\"?: Intl.DateTimeFormatOptions[\"numberingSystem\"],\n \"hour12\"?: Intl.DateTimeFormatOptions[\"hour12\"],\n \"hour-cycle\"?: Intl.DateTimeFormatOptions[\"hourCycle\"],\n \"time-zone\"?: Intl.DateTimeFormatOptions[\"timeZone\"],\n \"weekday\"?: Intl.DateTimeFormatOptions[\"weekday\"],\n \"era\"?: Intl.DateTimeFormatOptions[\"era\"],\n \"year\"?: Intl.DateTimeFormatOptions[\"year\"],\n \"month\"?: Intl.DateTimeFormatOptions[\"month\"],\n \"day\"?: Intl.DateTimeFormatOptions[\"day\"],\n \"day-period\"?: Intl.DateTimeFormatOptions[\"dayPeriod\"],\n \"hour\"?: Intl.DateTimeFormatOptions[\"hour\"],\n \"minute\"?: Intl.DateTimeFormatOptions[\"minute\"],\n \"second\"?: Intl.DateTimeFormatOptions[\"second\"],\n \"fractional-second-digits\"?: Intl.DateTimeFormatOptions[\"fractionalSecondDigits\"] | `${Intl.DateTimeFormatOptions[\"fractionalSecondDigits\"]}`,\n \"time-zone-name\"?: Intl.DateTimeFormatOptions[\"timeZoneName\"],\n \"format-matcher\"?: Intl.DateTimeFormatOptions[\"formatMatcher\"],\n \"date-style\"?: Intl.DateTimeFormatOptions[\"dateStyle\"],\n \"time-style\"?: Intl.DateTimeFormatOptions[\"timeStyle\"]\n }\n }\n}\n"],"names":["bySource","parts"],"mappings":"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"}