foldkit 0.33.6 → 0.34.1
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/README.md +19 -19
- package/dist/devtools/overlay.d.ts.map +1 -1
- package/dist/devtools/overlay.js +76 -33
- package/dist/html/index.d.ts +431 -5
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +1 -0
- package/dist/html/public.d.ts +1 -2
- package/dist/html/public.d.ts.map +1 -1
- package/dist/html/public.js +1 -2
- package/dist/task/dom.d.ts +6 -6
- package/dist/task/dom.js +6 -6
- package/dist/task/inert.d.ts +2 -2
- package/dist/task/inert.js +2 -2
- package/dist/task/scrollLock.d.ts +2 -2
- package/dist/task/scrollLock.js +2 -2
- package/dist/ui/checkbox/index.d.ts +5 -9
- package/dist/ui/checkbox/index.d.ts.map +1 -1
- package/dist/ui/checkbox/index.js +7 -10
- package/dist/ui/checkbox/public.d.ts +1 -1
- package/dist/ui/checkbox/public.d.ts.map +1 -1
- package/dist/ui/combobox/multi.d.ts +31 -10
- package/dist/ui/combobox/multi.d.ts.map +1 -1
- package/dist/ui/combobox/multi.js +1 -1
- package/dist/ui/combobox/public.d.ts +1 -1
- package/dist/ui/combobox/public.d.ts.map +1 -1
- package/dist/ui/combobox/shared.d.ts +53 -14
- package/dist/ui/combobox/shared.d.ts.map +1 -1
- package/dist/ui/combobox/shared.js +72 -28
- package/dist/ui/combobox/single.d.ts +31 -10
- package/dist/ui/combobox/single.d.ts.map +1 -1
- package/dist/ui/combobox/single.js +1 -1
- package/dist/ui/dialog/index.d.ts +14 -8
- package/dist/ui/dialog/index.d.ts.map +1 -1
- package/dist/ui/dialog/index.js +21 -12
- package/dist/ui/dialog/public.d.ts +1 -1
- package/dist/ui/dialog/public.d.ts.map +1 -1
- package/dist/ui/dialog/public.js +1 -1
- package/dist/ui/disclosure/index.d.ts +11 -8
- package/dist/ui/disclosure/index.d.ts.map +1 -1
- package/dist/ui/disclosure/index.js +20 -18
- package/dist/ui/disclosure/public.d.ts +1 -1
- package/dist/ui/disclosure/public.d.ts.map +1 -1
- package/dist/ui/listbox/multi.d.ts +34 -9
- package/dist/ui/listbox/multi.d.ts.map +1 -1
- package/dist/ui/listbox/multi.js +1 -1
- package/dist/ui/listbox/public.d.ts +1 -1
- package/dist/ui/listbox/public.d.ts.map +1 -1
- package/dist/ui/listbox/shared.d.ts +57 -13
- package/dist/ui/listbox/shared.d.ts.map +1 -1
- package/dist/ui/listbox/shared.js +77 -27
- package/dist/ui/listbox/single.d.ts +34 -9
- package/dist/ui/listbox/single.d.ts.map +1 -1
- package/dist/ui/listbox/single.js +1 -1
- package/dist/ui/menu/index.d.ts +39 -11
- package/dist/ui/menu/index.d.ts.map +1 -1
- package/dist/ui/menu/index.js +81 -32
- package/dist/ui/menu/public.d.ts +1 -1
- package/dist/ui/menu/public.d.ts.map +1 -1
- package/dist/ui/popover/index.d.ts +28 -12
- package/dist/ui/popover/index.d.ts.map +1 -1
- package/dist/ui/popover/index.js +50 -24
- package/dist/ui/popover/public.d.ts +1 -1
- package/dist/ui/popover/public.d.ts.map +1 -1
- package/dist/ui/radioGroup/index.d.ts +8 -7
- package/dist/ui/radioGroup/index.d.ts.map +1 -1
- package/dist/ui/radioGroup/index.js +12 -9
- package/dist/ui/radioGroup/public.d.ts +1 -1
- package/dist/ui/radioGroup/public.d.ts.map +1 -1
- package/dist/ui/switch/index.d.ts +5 -9
- package/dist/ui/switch/index.d.ts.map +1 -1
- package/dist/ui/switch/index.js +7 -10
- package/dist/ui/switch/public.d.ts +1 -1
- package/dist/ui/switch/public.d.ts.map +1 -1
- package/dist/ui/tabs/index.d.ts +13 -9
- package/dist/ui/tabs/index.d.ts.map +1 -1
- package/dist/ui/tabs/index.js +30 -17
- package/dist/ui/tabs/public.d.ts +1 -1
- package/dist/ui/tabs/public.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<picture>
|
|
3
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/
|
|
4
|
-
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/
|
|
5
|
-
<img src="https://raw.githubusercontent.com/
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/foldkit/foldkit/main/packages/website/public/logo-dark.svg">
|
|
4
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/foldkit/foldkit/main/packages/website/public/logo.svg">
|
|
5
|
+
<img src="https://raw.githubusercontent.com/foldkit/foldkit/main/packages/website/public/logo.svg" alt="Foldkit" width="350">
|
|
6
6
|
</picture>
|
|
7
7
|
</p>
|
|
8
8
|
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
<h3 align="center">The frontend framework for correctness.</h3>
|
|
14
14
|
|
|
15
15
|
<p align="center">
|
|
16
|
-
<a href="https://foldkit.dev"><strong>Documentation</strong></a> · <a href="https://github.com/
|
|
16
|
+
<a href="https://foldkit.dev"><strong>Documentation</strong></a> · <a href="https://github.com/foldkit/foldkit#examples"><strong>Examples</strong></a> · <a href="https://foldkit.dev/getting-started"><strong>Getting Started</strong></a>
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
Foldkit is
|
|
21
|
+
Foldkit is a frontend framework for TypeScript, built on [Effect](https://effect.website/), using [The Elm Architecture](https://guide.elm-lang.org/architecture/). One Model, one update function, one way to do things. No hooks, no local state, no hidden mutations.
|
|
22
22
|
|
|
23
23
|
> [!NOTE]
|
|
24
24
|
> Foldkit is pre-1.0. The core API is stable, but breaking changes may occur in minor releases. See the [changelog](./CHANGELOG.md) for details.
|
|
@@ -129,7 +129,7 @@ const element = Runtime.makeElement({
|
|
|
129
129
|
Runtime.run(element)
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
Source: [examples/counter/src/main.ts](https://github.com/
|
|
132
|
+
Source: [examples/counter/src/main.ts](https://github.com/foldkit/foldkit/blob/main/examples/counter/src/main.ts)
|
|
133
133
|
|
|
134
134
|
## What Ships With Foldkit
|
|
135
135
|
|
|
@@ -153,19 +153,19 @@ This is what makes Foldkit unusually AI-friendly. The same property that makes t
|
|
|
153
153
|
|
|
154
154
|
## Examples
|
|
155
155
|
|
|
156
|
-
- **[Counter](https://github.com/
|
|
157
|
-
- **[Todo](https://github.com/
|
|
158
|
-
- **[Stopwatch](https://github.com/
|
|
159
|
-
- **[Error View](https://github.com/
|
|
160
|
-
- **[Form](https://github.com/
|
|
161
|
-
- **[Weather](https://github.com/
|
|
162
|
-
- **[Routing](https://github.com/
|
|
163
|
-
- **[Query Sync](https://github.com/
|
|
164
|
-
- **[Snake](https://github.com/
|
|
165
|
-
- **[Auth](https://github.com/
|
|
166
|
-
- **[Shopping Cart](https://github.com/
|
|
167
|
-
- **[WebSocket Chat](https://github.com/
|
|
168
|
-
- **[Typing Game](https://github.com/
|
|
156
|
+
- **[Counter](https://github.com/foldkit/foldkit/blob/main/examples/counter/src/main.ts)** — Increment/decrement with reset
|
|
157
|
+
- **[Todo](https://github.com/foldkit/foldkit/blob/main/examples/todo/src/main.ts)** — CRUD operations with localStorage persistence
|
|
158
|
+
- **[Stopwatch](https://github.com/foldkit/foldkit/blob/main/examples/stopwatch/src/main.ts)** — Timer with start/stop/reset
|
|
159
|
+
- **[Error View](https://github.com/foldkit/foldkit/blob/main/examples/error-view/src/main.ts)** — Custom error fallback UI
|
|
160
|
+
- **[Form](https://github.com/foldkit/foldkit/blob/main/examples/form/src/main.ts)** — Form validation with async email checking
|
|
161
|
+
- **[Weather](https://github.com/foldkit/foldkit/blob/main/examples/weather/src/main.ts)** — HTTP requests with async state handling
|
|
162
|
+
- **[Routing](https://github.com/foldkit/foldkit/blob/main/examples/routing/src/main.ts)** — URL routing with parser combinators
|
|
163
|
+
- **[Query Sync](https://github.com/foldkit/foldkit/blob/main/examples/query-sync/src/main.ts)** — URL query parameter sync with filtering and sorting
|
|
164
|
+
- **[Snake](https://github.com/foldkit/foldkit/blob/main/examples/snake/src/main.ts)** — Classic game built with Subscriptions
|
|
165
|
+
- **[Auth](https://github.com/foldkit/foldkit/blob/main/examples/auth/src/main.ts)** — Authentication flow with Submodels and OutMessage
|
|
166
|
+
- **[Shopping Cart](https://github.com/foldkit/foldkit/blob/main/examples/shopping-cart/src/main.ts)** — Nested models and complex state
|
|
167
|
+
- **[WebSocket Chat](https://github.com/foldkit/foldkit/blob/main/examples/websocket-chat/src/main.ts)** — Managed Resources with WebSocket integration
|
|
168
|
+
- **[Typing Game](https://github.com/foldkit/foldkit/tree/main/packages/typing-game)** — Multiplayer typing game with Effect RPC backend
|
|
169
169
|
|
|
170
170
|
## License
|
|
171
171
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/devtools/overlay.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,MAAM,EAIN,MAAM,EAQP,MAAM,QAAQ,CAAA;AAOf,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAMxE,OAAO,EAAE,KAAK,aAAa,EAA+B,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/devtools/overlay.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,MAAM,EAIN,MAAM,EAQP,MAAM,QAAQ,CAAA;AAOf,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAMxE,OAAO,EAAE,KAAK,aAAa,EAA+B,MAAM,SAAS,CAAA;AA2yCzE,eAAO,MAAM,aAAa,GACxB,OAAO,aAAa,EACpB,UAAU,gBAAgB,EAC1B,MAAM,YAAY,EAClB,aAAa,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,sCA4ChC,CAAA"}
|
package/dist/devtools/overlay.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
2
|
import { Array as Array_, Effect, HashSet, Match as M, Number as Number_, Option, Predicate, Record, Schema as S, Stream, String as String_, SubscriptionRef, pipe, } from 'effect';
|
|
3
3
|
import { OptionExt } from '../effectExtensions';
|
|
4
|
-
import { html } from '../html';
|
|
4
|
+
import { createKeyedLazy, html } from '../html';
|
|
5
5
|
import { m } from '../message';
|
|
6
6
|
import { makeElement } from '../runtime/runtime';
|
|
7
7
|
import { makeSubscriptions } from '../runtime/subscription';
|
|
@@ -352,6 +352,8 @@ const PANEL_POSITION_CLASS = {
|
|
|
352
352
|
};
|
|
353
353
|
const makeView = (position, mode, maybeBanner) => {
|
|
354
354
|
const { div, header, span, ul, button, svg, path, keyed, Class, Style, OnClick, AriaHidden, Xmlns, Fill, ViewBox, StrokeWidth, Stroke, StrokeLinecap, StrokeLinejoin, D, } = html();
|
|
355
|
+
const lazyTreeNode = createKeyedLazy();
|
|
356
|
+
const lazyMessageRow = createKeyedLazy();
|
|
355
357
|
// JSON TREE
|
|
356
358
|
const leafValueView = (value) => M.value(value).pipe(M.when(Predicate.isNull, () => span([Class('json-null italic')], ['null'])), M.when(Predicate.isUndefined, () => span([Class('json-null italic')], ['undefined'])), M.when(Predicate.isString, stringValue => span([Class('json-string')], [`"${stringValue}"`])), M.when(Predicate.isNumber, numberValue => span([Class('json-number')], [String(numberValue)])), M.when(Predicate.isBoolean, booleanValue => span([Class('json-boolean')], [String(booleanValue)])), M.orElse(unknownValue => span([Class('json-null')], [String(unknownValue)])));
|
|
357
359
|
const keyView = (key) => span([Class('json-key')], [`${key}:\u00a0`]);
|
|
@@ -375,72 +377,103 @@ const makeView = (position, mode, maybeBanner) => {
|
|
|
375
377
|
const tagLabelView = (tag) => span([Class('json-tag')], [tag]);
|
|
376
378
|
const diffDotView = span([Class('diff-dot')], []);
|
|
377
379
|
const inlineDiffDotView = span([Class('diff-dot-inline')], []);
|
|
378
|
-
const flattenTree = (value, treePath,
|
|
380
|
+
const flattenTree = ({ value, treePath, depth, key, ...shared }) => {
|
|
381
|
+
const { expandedPaths, changedPaths, affectedPaths, accumulator, indentRootChildren, } = shared;
|
|
379
382
|
const isRoot = treePath === 'root';
|
|
380
383
|
const nodeIsExpandable = isExpandable(value);
|
|
381
384
|
const isExpanded = nodeIsExpandable && (isRoot || HashSet.has(expandedPaths, treePath));
|
|
382
|
-
const
|
|
385
|
+
const tag = isTagged(value) ? value._tag : '';
|
|
383
386
|
accumulator.push({
|
|
384
387
|
value,
|
|
385
388
|
treePath,
|
|
386
389
|
depth,
|
|
387
|
-
|
|
390
|
+
key,
|
|
388
391
|
isExpandable: nodeIsExpandable,
|
|
389
392
|
isExpanded,
|
|
390
393
|
isChanged: HashSet.has(changedPaths, treePath),
|
|
391
394
|
isAffected: HashSet.has(affectedPaths, treePath),
|
|
392
|
-
|
|
395
|
+
tag,
|
|
393
396
|
});
|
|
394
397
|
if (!isExpanded) {
|
|
395
398
|
return;
|
|
396
399
|
}
|
|
397
400
|
const childDepth = isRoot && !indentRootChildren ? depth : depth + 1;
|
|
398
401
|
if (Array.isArray(value)) {
|
|
399
|
-
value.forEach((item, arrayIndex) => flattenTree(
|
|
402
|
+
value.forEach((item, arrayIndex) => flattenTree({
|
|
403
|
+
...shared,
|
|
404
|
+
value: item,
|
|
405
|
+
treePath: `${treePath}.${arrayIndex}`,
|
|
406
|
+
depth: childDepth,
|
|
407
|
+
key: String(arrayIndex),
|
|
408
|
+
}));
|
|
400
409
|
}
|
|
401
410
|
else if (Predicate.isReadonlyRecord(value)) {
|
|
402
|
-
pipe(value, Record.toEntries, Array_.filter(([
|
|
411
|
+
pipe(value, Record.toEntries, Array_.filter(([entryKey]) => entryKey !== '_tag'), Array_.forEach(([entryKey, childValue]) => flattenTree({
|
|
412
|
+
...shared,
|
|
413
|
+
value: childValue,
|
|
414
|
+
treePath: `${treePath}.${entryKey}`,
|
|
415
|
+
depth: childDepth,
|
|
416
|
+
key: entryKey,
|
|
417
|
+
})));
|
|
403
418
|
}
|
|
404
419
|
};
|
|
405
|
-
const flatNodeView = (
|
|
406
|
-
const indent = Style({ paddingLeft: `${
|
|
407
|
-
const hasDiffDot =
|
|
408
|
-
if (!
|
|
420
|
+
const flatNodeView = (value, treePath, depth, key, nodeIsExpandable, isExpanded, isChanged, isAffected, tag) => {
|
|
421
|
+
const indent = Style({ paddingLeft: `${depth * TREE_INDENT_PX}px` });
|
|
422
|
+
const hasDiffDot = isChanged || isAffected;
|
|
423
|
+
if (!nodeIsExpandable) {
|
|
409
424
|
return div([
|
|
410
|
-
Class(clsx('tree-row flex items-center gap-px font-mono text-2xs',
|
|
425
|
+
Class(clsx('tree-row flex items-center gap-px font-mono text-2xs', isChanged && 'diff-changed')),
|
|
411
426
|
indent,
|
|
412
427
|
], [
|
|
413
428
|
...(hasDiffDot ? [diffDotView] : []),
|
|
414
|
-
...
|
|
415
|
-
leafValueView(
|
|
429
|
+
...(String_.isNonEmpty(key) ? [keyView(key)] : []),
|
|
430
|
+
leafValueView(value),
|
|
416
431
|
]);
|
|
417
432
|
}
|
|
418
|
-
const isRoot =
|
|
419
|
-
const preview =
|
|
420
|
-
? Array.isArray(
|
|
421
|
-
? `(${
|
|
433
|
+
const isRoot = treePath === 'root';
|
|
434
|
+
const preview = isExpanded
|
|
435
|
+
? Array.isArray(value)
|
|
436
|
+
? `(${value.length})`
|
|
422
437
|
: ''
|
|
423
|
-
: collapsedPreview(
|
|
438
|
+
: collapsedPreview(value);
|
|
424
439
|
return div([
|
|
425
|
-
Class(clsx('tree-row flex items-center gap-px font-mono text-2xs', !isRoot && 'tree-row-expandable cursor-pointer',
|
|
440
|
+
Class(clsx('tree-row flex items-center gap-px font-mono text-2xs', !isRoot && 'tree-row-expandable cursor-pointer', isChanged && 'diff-changed')),
|
|
426
441
|
indent,
|
|
427
|
-
...(isRoot ? [] : [OnClick(ToggledTreeNode({ path:
|
|
442
|
+
...(isRoot ? [] : [OnClick(ToggledTreeNode({ path: treePath }))]),
|
|
428
443
|
], [
|
|
429
|
-
...(isRoot ? [] : [arrowView(
|
|
444
|
+
...(isRoot ? [] : [arrowView(isExpanded)]),
|
|
430
445
|
...(!isRoot && hasDiffDot ? [diffDotView] : []),
|
|
431
|
-
...
|
|
432
|
-
|
|
433
|
-
Option.map(node.maybeTag, tagLabelView),
|
|
434
|
-
]),
|
|
446
|
+
...(String_.isNonEmpty(key) ? [keyView(key)] : []),
|
|
447
|
+
...(String_.isNonEmpty(tag) ? [tagLabelView(tag)] : []),
|
|
435
448
|
span([Class('json-preview')], [preview]),
|
|
436
449
|
]);
|
|
437
450
|
};
|
|
438
451
|
const treeView = (value, rootPath, expandedPaths, changedPaths, affectedPaths, maybeRootLabel, indentRootChildren) => {
|
|
439
452
|
const nodes = [];
|
|
440
|
-
flattenTree(
|
|
453
|
+
flattenTree({
|
|
454
|
+
value,
|
|
455
|
+
treePath: rootPath,
|
|
456
|
+
expandedPaths,
|
|
457
|
+
changedPaths,
|
|
458
|
+
affectedPaths,
|
|
459
|
+
depth: 0,
|
|
460
|
+
key: Option.getOrElse(maybeRootLabel, () => ''),
|
|
461
|
+
accumulator: nodes,
|
|
462
|
+
indentRootChildren,
|
|
463
|
+
});
|
|
441
464
|
return div([
|
|
442
465
|
Class('inspector-tree flex-1 overflow-auto min-h-0 min-w-0 overscroll-none'),
|
|
443
|
-
], nodes.map(flatNodeView
|
|
466
|
+
], nodes.map(node => lazyTreeNode(node.treePath, flatNodeView, [
|
|
467
|
+
node.value,
|
|
468
|
+
node.treePath,
|
|
469
|
+
node.depth,
|
|
470
|
+
node.key,
|
|
471
|
+
node.isExpandable,
|
|
472
|
+
node.isExpanded,
|
|
473
|
+
node.isChanged,
|
|
474
|
+
node.isAffected,
|
|
475
|
+
node.tag,
|
|
476
|
+
])));
|
|
444
477
|
};
|
|
445
478
|
const inspectedTimestamp = (model) => {
|
|
446
479
|
const lastIndex = Array_.isEmptyReadonlyArray(model.entries)
|
|
@@ -490,12 +523,15 @@ const makeView = (position, mode, maybeBanner) => {
|
|
|
490
523
|
model: model.inspectorTabs,
|
|
491
524
|
toMessage: tabsMessage => GotInspectorTabsMessage({ message: tabsMessage }),
|
|
492
525
|
tabs: INSPECTOR_TABS,
|
|
493
|
-
|
|
494
|
-
|
|
526
|
+
tabListAriaLabel: 'Inspector tabs',
|
|
527
|
+
attributes: [Class('flex flex-col flex-1 min-h-0')],
|
|
528
|
+
tabListAttributes: [Class('flex border-b shrink-0')],
|
|
495
529
|
tabToConfig: (tab, { isActive }) => ({
|
|
496
|
-
|
|
530
|
+
buttonAttributes: [
|
|
531
|
+
Class(clsx('dt-tab-button cursor-pointer text-base font-mono px-3 py-1', isActive ? 'text-dt dt-tab-active' : 'text-dt-muted')),
|
|
532
|
+
],
|
|
497
533
|
buttonContent: span([], [tab]),
|
|
498
|
-
|
|
534
|
+
panelAttributes: [Class('flex flex-col flex-1 min-h-0 min-w-0')],
|
|
499
535
|
panelContent: Option.match(model.maybeInspectedModel, {
|
|
500
536
|
onNone: () => emptyInspectorView,
|
|
501
537
|
onSome: inspectedModel => inspectorTabContent(model, tab, inspectedModel),
|
|
@@ -608,7 +644,14 @@ const makeView = (position, mode, maybeBanner) => {
|
|
|
608
644
|
const absoluteIndex = model.startIndex + arrayIndex;
|
|
609
645
|
const isSelected = selectedIndex === absoluteIndex;
|
|
610
646
|
const isPausedHere = model.isPaused && model.pausedAtIndex === absoluteIndex;
|
|
611
|
-
return
|
|
647
|
+
return lazyMessageRow(String(absoluteIndex), messageRowView, [
|
|
648
|
+
entry.tag,
|
|
649
|
+
absoluteIndex,
|
|
650
|
+
isSelected,
|
|
651
|
+
isPausedHere,
|
|
652
|
+
entry.timestamp - baseTimestamp,
|
|
653
|
+
entry.isModelChanged,
|
|
654
|
+
]);
|
|
612
655
|
}), Array_.reverse);
|
|
613
656
|
return ul([Class('message-list flex-1 overflow-y-auto min-h-0 overscroll-none')], [
|
|
614
657
|
...messageRows,
|