@gyral/core 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +112 -0
- package/LICENSE +1 -1
- package/NOTICE +1 -1
- package/README.md +9 -7
- package/dist/children.d.ts +5 -2
- package/dist/children.js +8 -3
- package/dist/children.js.map +1 -1
- package/dist/command.js +6 -0
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +21 -0
- package/dist/compiler/ast.js +145 -0
- package/dist/compiler/ast.js.map +1 -0
- package/dist/compiler/compile.d.ts +38 -0
- package/dist/compiler/compile.js +129 -0
- package/dist/compiler/compile.js.map +1 -0
- package/dist/compiler/hooks.d.ts +18 -0
- package/dist/compiler/hooks.js +186 -0
- package/dist/compiler/hooks.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +21 -0
- package/dist/compiler/parse5-check.js +55 -0
- package/dist/compiler/parse5-check.js.map +1 -0
- package/dist/compiler/scan.d.ts +31 -0
- package/dist/compiler/scan.js +152 -0
- package/dist/compiler/scan.js.map +1 -0
- package/dist/compiler/source.d.ts +34 -0
- package/dist/compiler/source.js +114 -0
- package/dist/compiler/source.js.map +1 -0
- package/dist/define.d.ts +2 -2
- package/dist/define.js +35 -334
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +5 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +1 -0
- package/dist/devtools-off.js +1 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +1 -0
- package/dist/devtools.js +3 -0
- package/dist/devtools.js.map +1 -1
- package/dist/drivers-scope.d.ts +1 -1
- package/dist/drivers-scope.js +1 -8
- package/dist/drivers-scope.js.map +1 -1
- package/dist/element-types.d.ts +5 -3
- package/dist/element-types.js.map +1 -1
- package/dist/element.d.ts +3 -0
- package/dist/element.js +269 -0
- package/dist/element.js.map +1 -0
- package/dist/eslint/imports.d.ts +24 -0
- package/dist/eslint/imports.js +78 -0
- package/dist/eslint/imports.js.map +1 -0
- package/dist/eslint/index.d.ts +15 -0
- package/dist/eslint/index.js +15 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/locate.d.ts +33 -0
- package/dist/eslint/locate.js +132 -0
- package/dist/eslint/locate.js.map +1 -0
- package/dist/eslint/row-purity-rule.d.ts +2 -0
- package/dist/eslint/row-purity-rule.js +103 -0
- package/dist/eslint/row-purity-rule.js.map +1 -0
- package/dist/eslint/template-rule.d.ts +5 -0
- package/dist/eslint/template-rule.js +66 -0
- package/dist/eslint/template-rule.js.map +1 -0
- package/dist/features.d.ts +39 -0
- package/dist/features.js +2 -0
- package/dist/features.js.map +1 -0
- package/dist/focus.d.ts +9 -2
- package/dist/focus.js +17 -2
- package/dist/focus.js.map +1 -1
- package/dist/hooks/invalid.d.ts +14 -0
- package/dist/hooks/invalid.js +72 -0
- package/dist/hooks/invalid.js.map +1 -0
- package/dist/hooks/labelled-by.d.ts +13 -0
- package/dist/hooks/labelled-by.js +51 -0
- package/dist/hooks/labelled-by.js.map +1 -0
- package/dist/host-model.d.ts +48 -0
- package/dist/host-model.js +155 -0
- package/dist/host-model.js.map +1 -0
- package/dist/hydration-client.d.ts +9 -0
- package/dist/hydration-client.js +35 -0
- package/dist/hydration-client.js.map +1 -0
- package/dist/hydration.d.ts +13 -19
- package/dist/hydration.js +45 -45
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +9 -16
- package/dist/index.js +9 -16
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +31 -8
- package/dist/intent.js +82 -27
- package/dist/intent.js.map +1 -1
- package/dist/internal/interpreter.d.ts +7 -1
- package/dist/internal/interpreter.js +118 -73
- package/dist/internal/interpreter.js.map +1 -1
- package/dist/invokers-shim.d.ts +6 -0
- package/dist/invokers-shim.js +32 -0
- package/dist/invokers-shim.js.map +1 -0
- package/dist/invokers.d.ts +3 -5
- package/dist/invokers.js +11 -51
- package/dist/invokers.js.map +1 -1
- package/dist/islands.d.ts +0 -2
- package/dist/islands.js +4 -11
- package/dist/islands.js.map +1 -1
- package/dist/light-dom.d.ts +3 -52
- package/dist/light-dom.js +5 -100
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +66 -0
- package/dist/prop.js +22 -0
- package/dist/prop.js.map +1 -0
- package/dist/props.d.ts +52 -21
- package/dist/props.js +150 -34
- package/dist/props.js.map +1 -1
- package/dist/scheduler.d.ts +39 -0
- package/dist/scheduler.js +230 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/server-component.d.ts +10 -0
- package/dist/server-component.js +102 -0
- package/dist/server-component.js.map +1 -0
- package/dist/server-specs.d.ts +6 -0
- package/dist/server-specs.js +13 -0
- package/dist/server-specs.js.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.js +50 -0
- package/dist/server.js.map +1 -0
- package/dist/settled.d.ts +10 -0
- package/dist/settled.js +40 -0
- package/dist/settled.js.map +1 -0
- package/dist/states.d.ts +3 -3
- package/dist/states.js +4 -7
- package/dist/states.js.map +1 -1
- package/dist/store-binding.d.ts +6 -3
- package/dist/store-binding.js +5 -6
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +6 -7
- package/dist/store-scope.js +11 -26
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.js +9 -2
- package/dist/store.js.map +1 -1
- package/dist/stores-provider.d.ts +2 -6
- package/dist/stores-provider.js +21 -55
- package/dist/stores-provider.js.map +1 -1
- package/dist/transitions.d.ts +5 -6
- package/dist/transitions.js +11 -20
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +19 -23
- package/dist/types.js.map +1 -1
- package/dist/view/attributes.d.ts +6 -0
- package/dist/view/attributes.js +10 -0
- package/dist/view/attributes.js.map +1 -0
- package/dist/view/compiled.d.ts +1 -0
- package/dist/view/compiled.js +6 -0
- package/dist/view/compiled.js.map +1 -0
- package/dist/view/dev-off.d.ts +1 -0
- package/dist/view/dev-off.js +4 -0
- package/dist/view/dev-off.js.map +1 -0
- package/dist/view/dev.d.ts +1 -0
- package/dist/view/dev.js +5 -0
- package/dist/view/dev.js.map +1 -0
- package/dist/view/flags.d.ts +1 -0
- package/dist/view/flags.js +4 -0
- package/dist/view/flags.js.map +1 -0
- package/dist/view/index.d.ts +21 -0
- package/dist/view/index.js +21 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/normalize/check.d.ts +20 -0
- package/dist/view/normalize/check.js +78 -0
- package/dist/view/normalize/check.js.map +1 -0
- package/dist/view/normalize/emit.d.ts +13 -0
- package/dist/view/normalize/emit.js +136 -0
- package/dist/view/normalize/emit.js.map +1 -0
- package/dist/view/normalize/entities.d.ts +4 -0
- package/dist/view/normalize/entities.js +38 -0
- package/dist/view/normalize/entities.js.map +1 -0
- package/dist/view/normalize/errors.d.ts +9 -0
- package/dist/view/normalize/errors.js +19 -0
- package/dist/view/normalize/errors.js.map +1 -0
- package/dist/view/normalize/id.d.ts +7 -0
- package/dist/view/normalize/id.js +48 -0
- package/dist/view/normalize/id.js.map +1 -0
- package/dist/view/normalize/normalize.d.ts +15 -0
- package/dist/view/normalize/normalize.js +36 -0
- package/dist/view/normalize/normalize.js.map +1 -0
- package/dist/view/normalize/repairs.d.ts +24 -0
- package/dist/view/normalize/repairs.js +166 -0
- package/dist/view/normalize/repairs.js.map +1 -0
- package/dist/view/normalize/rules.d.ts +30 -0
- package/dist/view/normalize/rules.js +90 -0
- package/dist/view/normalize/rules.js.map +1 -0
- package/dist/view/normalize/shape.d.ts +5 -0
- package/dist/view/normalize/shape.js +38 -0
- package/dist/view/normalize/shape.js.map +1 -0
- package/dist/view/normalize/source.d.ts +13 -0
- package/dist/view/normalize/source.js +34 -0
- package/dist/view/normalize/source.js.map +1 -0
- package/dist/view/normalize/tag-states.d.ts +23 -0
- package/dist/view/normalize/tag-states.js +192 -0
- package/dist/view/normalize/tag-states.js.map +1 -0
- package/dist/view/normalize/tokenizer.d.ts +5 -0
- package/dist/view/normalize/tokenizer.js +233 -0
- package/dist/view/normalize/tokenizer.js.map +1 -0
- package/dist/view/normalize/tokens.d.ts +51 -0
- package/dist/view/normalize/tokens.js +24 -0
- package/dist/view/normalize/tokens.js.map +1 -0
- package/dist/view/normalize/tree.d.ts +59 -0
- package/dist/view/normalize/tree.js +190 -0
- package/dist/view/normalize/tree.js.map +1 -0
- package/dist/view/normalize/types.d.ts +126 -0
- package/dist/view/normalize/types.js +26 -0
- package/dist/view/normalize/types.js.map +1 -0
- package/dist/view/normalize/whitespace.d.ts +2 -0
- package/dist/view/normalize/whitespace.js +182 -0
- package/dist/view/normalize/whitespace.js.map +1 -0
- package/dist/view/prepare-stub.d.ts +3 -0
- package/dist/view/prepare-stub.js +7 -0
- package/dist/view/prepare-stub.js.map +1 -0
- package/dist/view/prepare.d.ts +8 -0
- package/dist/view/prepare.js +57 -0
- package/dist/view/prepare.js.map +1 -0
- package/dist/view/registry.d.ts +63 -0
- package/dist/view/registry.js +19 -0
- package/dist/view/registry.js.map +1 -0
- package/dist/view/render/adopt-attr.d.ts +14 -0
- package/dist/view/render/adopt-attr.js +77 -0
- package/dist/view/render/adopt-attr.js.map +1 -0
- package/dist/view/render/adopt-plan.d.ts +10 -0
- package/dist/view/render/adopt-plan.js +26 -0
- package/dist/view/render/adopt-plan.js.map +1 -0
- package/dist/view/render/adopt.d.ts +3 -0
- package/dist/view/render/adopt.js +269 -0
- package/dist/view/render/adopt.js.map +1 -0
- package/dist/view/render/attr-parts.d.ts +61 -0
- package/dist/view/render/attr-parts.js +229 -0
- package/dist/view/render/attr-parts.js.map +1 -0
- package/dist/view/render/child-part.d.ts +51 -0
- package/dist/view/render/child-part.js +170 -0
- package/dist/view/render/child-part.js.map +1 -0
- package/dist/view/render/dev-check.d.ts +12 -0
- package/dist/view/render/dev-check.js +122 -0
- package/dist/view/render/dev-check.js.map +1 -0
- package/dist/view/render/hook-part.d.ts +3 -0
- package/dist/view/render/hook-part.js +20 -0
- package/dist/view/render/hook-part.js.map +1 -0
- package/dist/view/render/hooks.d.ts +40 -0
- package/dist/view/render/hooks.js +46 -0
- package/dist/view/render/hooks.js.map +1 -0
- package/dist/view/render/hydrate.d.ts +10 -0
- package/dist/view/render/hydrate.js +33 -0
- package/dist/view/render/hydrate.js.map +1 -0
- package/dist/view/render/instance.d.ts +33 -0
- package/dist/view/render/instance.js +107 -0
- package/dist/view/render/instance.js.map +1 -0
- package/dist/view/render/list.d.ts +20 -0
- package/dist/view/render/list.js +156 -0
- package/dist/view/render/list.js.map +1 -0
- package/dist/view/render/mismatch.d.ts +10 -0
- package/dist/view/render/mismatch.js +53 -0
- package/dist/view/render/mismatch.js.map +1 -0
- package/dist/view/render/nodes.d.ts +10 -0
- package/dist/view/render/nodes.js +37 -0
- package/dist/view/render/nodes.js.map +1 -0
- package/dist/view/render/place.d.ts +18 -0
- package/dist/view/render/place.js +69 -0
- package/dist/view/render/place.js.map +1 -0
- package/dist/view/render/plan.d.ts +26 -0
- package/dist/view/render/plan.js +124 -0
- package/dist/view/render/plan.js.map +1 -0
- package/dist/view/render/raw.d.ts +18 -0
- package/dist/view/render/raw.js +68 -0
- package/dist/view/render/raw.js.map +1 -0
- package/dist/view/render/render.d.ts +12 -0
- package/dist/view/render/render.js +60 -0
- package/dist/view/render/render.js.map +1 -0
- package/dist/view/render/reorder.d.ts +4 -0
- package/dist/view/render/reorder.js +101 -0
- package/dist/view/render/reorder.js.map +1 -0
- package/dist/view/render/rows.d.ts +23 -0
- package/dist/view/render/rows.js +95 -0
- package/dist/view/render/rows.js.map +1 -0
- package/dist/view/render/seen.d.ts +11 -0
- package/dist/view/render/seen.js +17 -0
- package/dist/view/render/seen.js.map +1 -0
- package/dist/view/render/values.d.ts +29 -0
- package/dist/view/render/values.js +13 -0
- package/dist/view/render/values.js.map +1 -0
- package/dist/view/render/warn.d.ts +14 -0
- package/dist/view/render/warn.js +69 -0
- package/dist/view/render/warn.js.map +1 -0
- package/dist/view/server/component.d.ts +9 -0
- package/dist/view/server/component.js +42 -0
- package/dist/view/server/component.js.map +1 -0
- package/dist/view/server/escape.d.ts +10 -0
- package/dist/view/server/escape.js +34 -0
- package/dist/view/server/escape.js.map +1 -0
- package/dist/view/server/index.d.ts +28 -0
- package/dist/view/server/index.js +72 -0
- package/dist/view/server/index.js.map +1 -0
- package/dist/view/server/sha256.d.ts +2 -0
- package/dist/view/server/sha256.js +75 -0
- package/dist/view/server/sha256.js.map +1 -0
- package/dist/view/server/tags.d.ts +57 -0
- package/dist/view/server/tags.js +121 -0
- package/dist/view/server/tags.js.map +1 -0
- package/dist/view/server/values.d.ts +16 -0
- package/dist/view/server/values.js +86 -0
- package/dist/view/server/values.js.map +1 -0
- package/dist/view/server/writer.d.ts +16 -0
- package/dist/view/server/writer.js +155 -0
- package/dist/view/server/writer.js.map +1 -0
- package/dist/view/styles.d.ts +25 -0
- package/dist/view/styles.js +58 -0
- package/dist/view/styles.js.map +1 -0
- package/dist/view/template-element.d.ts +3 -0
- package/dist/view/template-element.js +25 -0
- package/dist/view/template-element.js.map +1 -0
- package/dist/view/template.d.ts +21 -0
- package/dist/view/template.js +30 -0
- package/dist/view/template.js.map +1 -0
- package/dist/vite.d.ts +45 -6
- package/dist/vite.js +150 -25
- package/dist/vite.js.map +1 -1
- package/package.json +41 -7
- package/dist/accessible-name.d.ts +0 -19
- package/dist/accessible-name.js +0 -56
- package/dist/accessible-name.js.map +0 -1
- package/dist/element-directive.d.ts +0 -20
- package/dist/element-directive.js +0 -31
- package/dist/element-directive.js.map +0 -1
- package/dist/internal/runtime.d.ts +0 -7
- package/dist/internal/runtime.js +0 -8
- package/dist/internal/runtime.js.map +0 -1
- package/dist/invalid.d.ts +0 -21
- package/dist/invalid.js +0 -70
- package/dist/invalid.js.map +0 -1
- package/dist/live-boolean.d.ts +0 -22
- package/dist/live-boolean.js +0 -34
- package/dist/live-boolean.js.map +0 -1
- package/dist/styles.d.ts +0 -12
- package/dist/styles.js +0 -11
- package/dist/styles.js.map +0 -1
- package/dist/textarea.d.ts +0 -26
- package/dist/textarea.js +0 -85
- package/dist/textarea.js.map +0 -1
package/dist/vite.js
CHANGED
|
@@ -1,37 +1,162 @@
|
|
|
1
|
-
// Vite / Vitest settings every Gyral app needs (gyral-a7r, docs/references/consumer-setup.md)
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
// Vite / Vitest settings every Gyral app needs (gyral-a7r, docs/references/consumer-setup.md):
|
|
2
|
+
// the template compiler (view/01-templates.md "Compiled") and, in serve mode, development
|
|
3
|
+
// output from the dev server's SSR (view/06-server.md "Development markers"). Only Node
|
|
4
|
+
// built-ins are imported up front, so it loads from vite.config.ts and vitest.config.ts in any
|
|
5
|
+
// way: bundled with the config, by Node from source (type stripping), or by a Vite module
|
|
6
|
+
// runner. The compiler is a plugin applied in `vite build` only, so dev servers and test runs
|
|
7
|
+
// keep the runtime template path; its implementation (./compiler/) loads on the first build
|
|
8
|
+
// hook, with `require` (Node loads ES modules with it too): a module runner that loaded this
|
|
9
|
+
// file may be closed by then, and would reject a dynamic import().
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import { createRequire } from 'node:module';
|
|
12
|
+
import { dirname, join, resolve } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
/** Where the view layer's `html` comes from: core's main entry (ADR 0018, Phase 3). */
|
|
15
|
+
export const DEFAULT_TEMPLATE_SOURCES = ['@gyral/core'];
|
|
16
|
+
/** The resolve condition that maps core's `#prepare` to its stub (ADR 0017's mechanism). */
|
|
17
|
+
export const COMPILED_CONDITION = 'gyral-compiled';
|
|
18
|
+
/** Vite 8's default resolve conditions (`defaultClientConditions`, server ones without browser). */
|
|
19
|
+
export const CLIENT_CONDITIONS = ['module', 'browser', 'development|production'];
|
|
20
|
+
export const SERVER_CONDITIONS = ['module', 'node', 'development|production'];
|
|
12
21
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
22
|
+
* Adds the `gyral-compiled` condition to an environment, on top of the app's conditions or
|
|
23
|
+
* Vite's defaults: Vite replaces the defaults when a config names any condition.
|
|
15
24
|
*/
|
|
16
|
-
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
function addCondition(name, config, env) {
|
|
26
|
+
const consumer = config.consumer ?? (name === 'client' ? 'client' : 'server');
|
|
27
|
+
const client = consumer === 'client' || env.isSsrTargetWebworker === true;
|
|
28
|
+
const current = config.resolve?.conditions ?? (client ? CLIENT_CONDITIONS : SERVER_CONDITIONS);
|
|
29
|
+
if (!current.includes(COMPILED_CONDITION)) {
|
|
30
|
+
config.resolve = { ...config.resolve, conditions: [...current, COMPILED_CONDITION] };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The compiler's hooks. From core's TypeScript source (this workspace, `link:` checkouts) they
|
|
35
|
+
* load through Vite's module runner, as a vite.config.ts would; from the published package,
|
|
36
|
+
* with require.
|
|
37
|
+
*/
|
|
38
|
+
async function loadHooks(options) {
|
|
39
|
+
const settings = {
|
|
40
|
+
sources: options.sources ?? DEFAULT_TEMPLATE_SOURCES,
|
|
41
|
+
parse5: options.parse5 === false
|
|
42
|
+
? undefined
|
|
43
|
+
: typeof options.parse5 === 'string'
|
|
44
|
+
? options.parse5
|
|
45
|
+
: 'parse5',
|
|
46
|
+
};
|
|
47
|
+
const require = createRequire(import.meta.url);
|
|
48
|
+
if (!import.meta.url.endsWith('.ts')) {
|
|
49
|
+
return require('./compiler/hooks.js').createCompiler(settings);
|
|
50
|
+
}
|
|
51
|
+
const { runnerImport } = require('vite');
|
|
52
|
+
const nodeEnv = process.env['NODE_ENV']; // the runner sets it when unset; the build owns it
|
|
53
|
+
const { module } = await runnerImport(fileURLToPath(new URL('./compiler/hooks.ts', import.meta.url)), { configFile: false, logLevel: 'silent' });
|
|
54
|
+
if (nodeEnv === undefined)
|
|
55
|
+
delete process.env['NODE_ENV'];
|
|
56
|
+
else
|
|
57
|
+
process.env['NODE_ENV'] = nodeEnv;
|
|
58
|
+
return module.createCompiler(settings);
|
|
59
|
+
}
|
|
60
|
+
/** The template compiler alone (`gyralVitePreset()` includes it). */
|
|
61
|
+
export function gyralTemplateCompiler(options = {}) {
|
|
62
|
+
let hooks;
|
|
63
|
+
const ready = () => {
|
|
64
|
+
if (hooks === undefined)
|
|
65
|
+
throw new Error('gyral: the template compiler is not loaded yet');
|
|
66
|
+
return hooks;
|
|
67
|
+
};
|
|
68
|
+
return {
|
|
69
|
+
name: 'gyral:template-compiler',
|
|
70
|
+
enforce: 'pre',
|
|
71
|
+
apply: 'build',
|
|
72
|
+
configEnvironment: addCondition,
|
|
73
|
+
async configResolved(config) {
|
|
74
|
+
hooks = await loadHooks(options);
|
|
75
|
+
await hooks.configResolved.call(this, config);
|
|
76
|
+
},
|
|
77
|
+
buildStart(input) {
|
|
78
|
+
return ready().buildStart.call(this, input);
|
|
79
|
+
},
|
|
80
|
+
transform: {
|
|
81
|
+
filter: { id: /\.[cm]?[jt]sx?$/, code: 'html' },
|
|
82
|
+
handler(code, id, opts) {
|
|
83
|
+
return ready().transform.call(this, code, id, opts);
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
generateBundle(output, bundle, isWrite) {
|
|
87
|
+
return ready().generateBundle.call(this, output, bundle, isWrite);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** Gyral's packages: the dev server runs them through Vite, never Node (view/06). */
|
|
92
|
+
export const GYRAL_PACKAGES = /^@gyral\//;
|
|
93
|
+
function manifest(file) {
|
|
94
|
+
try {
|
|
95
|
+
return JSON.parse(readFileSync(file, 'utf8'));
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** The installed manifest of `name`, looked up from `root` the way Node does (no exports map). */
|
|
102
|
+
function installed(root, name) {
|
|
103
|
+
for (let dir = root;; dir = dirname(dir)) {
|
|
104
|
+
const found = manifest(join(dir, 'node_modules', name, 'package.json'));
|
|
105
|
+
if (found !== undefined || dirname(dir) === dir)
|
|
106
|
+
return found;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The app's direct dependencies that depend on a Gyral package (a design system, say). They
|
|
111
|
+
* import @gyral/core, so they must share the copy the dev server runs.
|
|
112
|
+
*/
|
|
113
|
+
export function gyralDependents(root) {
|
|
114
|
+
const app = manifest(join(root, 'package.json'));
|
|
115
|
+
const names = Object.keys({ ...app?.dependencies, ...app?.devDependencies });
|
|
116
|
+
return names.filter((name) => {
|
|
117
|
+
if (GYRAL_PACKAGES.test(name))
|
|
118
|
+
return false;
|
|
119
|
+
const dep = installed(root, name);
|
|
120
|
+
return Object.keys({ ...dep?.dependencies, ...dep?.peerDependencies }).some((d) => GYRAL_PACKAGES.test(d));
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Development output from the dev server's SSR (`ssrLoadModule`, view/06 "Development
|
|
125
|
+
* markers"). Vite externalizes installed packages there and Node imports them itself, resolving
|
|
126
|
+
* core's `#view-dev` without the `development` condition (Vite's `externalConditions` only pick
|
|
127
|
+
* the entry file, not the package's own imports), so the server rendered production output.
|
|
128
|
+
* In serve mode this plugin keeps Gyral's packages, and the app's dependencies that use them,
|
|
129
|
+
* out of externalization in server environments: Vite resolves them with its conditions
|
|
130
|
+
* (`development` in dev), and they all share one copy of core. `vite build` is unaffected.
|
|
131
|
+
*/
|
|
132
|
+
export function gyralDevServer() {
|
|
133
|
+
let root = process.cwd();
|
|
134
|
+
return {
|
|
135
|
+
name: 'gyral:dev-server',
|
|
136
|
+
apply: 'serve',
|
|
137
|
+
config(config) {
|
|
138
|
+
root = resolve(config.root ?? process.cwd());
|
|
139
|
+
},
|
|
140
|
+
configEnvironment(name, config) {
|
|
141
|
+
const consumer = config.consumer ?? (name === 'client' ? 'client' : 'server');
|
|
142
|
+
if (consumer === 'client')
|
|
143
|
+
return undefined;
|
|
144
|
+
return { resolve: { noExternal: [GYRAL_PACKAGES, ...gyralDependents(root)] } };
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
26
148
|
/**
|
|
27
149
|
* Spread into a Vite config, or into each Vitest project:
|
|
28
150
|
*
|
|
29
151
|
* export default defineConfig({ ...gyralVitePreset(), build: { … } });
|
|
152
|
+
*
|
|
153
|
+
* With plugins of your own, list both: `plugins: [...preset.plugins, mine()]`.
|
|
30
154
|
*/
|
|
31
155
|
export function gyralVitePreset(options = {}) {
|
|
32
156
|
return {
|
|
33
|
-
|
|
34
|
-
|
|
157
|
+
plugins: [gyralTemplateCompiler(options.compiler), gyralDevServer()],
|
|
158
|
+
resolve: { dedupe: [] },
|
|
159
|
+
optimizeDeps: { include: [...new Set(options.optimize ?? [])] },
|
|
35
160
|
};
|
|
36
161
|
}
|
|
37
162
|
//# sourceMappingURL=vite.js.map
|
package/dist/vite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,iFAAiF;AAEjF,6FAA6F;AAC7F,MAAM,CAAC,MAAM,YAAY,GAAsB;IAC7C,KAAK;IACL,UAAU;IACV,aAAa;IACb,uBAAuB;IACvB,eAAe;IACf,sBAAsB;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,KAAK;IACL,kBAAkB;IAClB,oBAAoB;IACpB,6BAA6B;IAC7B,yBAAyB;IACzB,wBAAwB;IACxB,0BAA0B;IAC1B,6BAA6B;CAC9B,CAAC;AAYF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,UAA4B,EAAE;IAC5D,OAAO;QACL,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC,EAAE;QACtC,YAAY,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;KACzF,CAAC;AACJ,CAAC","sourcesContent":["// Vite / Vitest settings every Gyral app needs (gyral-a7r, docs/references/consumer-setup.md).\n// Plain data, no imports: safe to load from vite.config.ts and vitest.config.ts.\n\n/** Every Lit package: resolve exactly one copy, even when Gyral is linked from elsewhere. */\nexport const LIT_PACKAGES: readonly string[] = [\n 'lit',\n 'lit-html',\n 'lit-element',\n '@lit/reactive-element',\n '@lit-labs/ssr',\n '@lit-labs/ssr-client',\n];\n\n/**\n * Lit modules that Gyral imports or re-exports. Pre-bundling them up front stops Vite from\n * discovering them mid-run, which reloads the page and fails the first browser test run.\n */\nexport const LIT_PREBUNDLE: readonly string[] = [\n 'lit',\n 'lit/directive.js',\n 'lit/static-html.js',\n 'lit/directives/class-map.js',\n 'lit/directives/keyed.js',\n 'lit/directives/live.js',\n 'lit/directives/repeat.js',\n 'lit/directives/style-map.js',\n];\n\nexport interface GyralViteOptions {\n /** More modules to pre-bundle (e.g. 'lit/directives/unsafe-html.js'). */\n readonly optimize?: readonly string[];\n}\n\nexport interface GyralViteConfig {\n readonly resolve: { readonly dedupe: string[] };\n readonly optimizeDeps: { readonly include: string[] };\n}\n\n/**\n * Spread into a Vite config, or into each Vitest project:\n *\n * export default defineConfig({ ...gyralVitePreset(), build: { … } });\n */\nexport function gyralVitePreset(options: GyralViteOptions = {}): GyralViteConfig {\n return {\n resolve: { dedupe: [...LIT_PACKAGES] },\n optimizeDeps: { include: [...new Set([...LIT_PREBUNDLE, ...(options.optimize ?? [])])] },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"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","sourcesContent":["// Vite / Vitest settings every Gyral app needs (gyral-a7r, docs/references/consumer-setup.md):\n// the template compiler (view/01-templates.md \"Compiled\") and, in serve mode, development\n// output from the dev server's SSR (view/06-server.md \"Development markers\"). Only Node\n// built-ins are imported up front, so it loads from vite.config.ts and vitest.config.ts in any\n// way: bundled with the config, by Node from source (type stripping), or by a Vite module\n// runner. The compiler is a plugin applied in `vite build` only, so dev servers and test runs\n// keep the runtime template path; its implementation (./compiler/) loads on the first build\n// hook, with `require` (Node loads ES modules with it too): a module runner that loaded this\n// file may be closed by then, and would reject a dynamic import().\nimport { readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { ConfigEnv, EnvironmentOptions, Plugin } from 'vite';\nimport type { CompilerHooks } from './compiler/hooks.js';\n\nexport interface TemplateCompilerOptions {\n /**\n * Module specifiers whose `html` export is the view layer's tag (default\n * `DEFAULT_TEMPLATE_SOURCES`). An import matches when its specifier is listed, or when it\n * resolves to the same module as a listed one; core's own view modules always match. A\n * source other than '@gyral/core' must also export `compiled`.\n */\n readonly sources?: readonly string[];\n /**\n * Rule 7's extra check with parse5 (an optional peer dependency): `true` (default) uses\n * 'parse5' when it is installed, a string names the module to load, `false` skips it.\n */\n readonly parse5?: boolean | string;\n}\n\n/** Where the view layer's `html` comes from: core's main entry (ADR 0018, Phase 3). */\nexport const DEFAULT_TEMPLATE_SOURCES: readonly string[] = ['@gyral/core'];\n\n/** The resolve condition that maps core's `#prepare` to its stub (ADR 0017's mechanism). */\nexport const COMPILED_CONDITION = 'gyral-compiled';\n/** Vite 8's default resolve conditions (`defaultClientConditions`, server ones without browser). */\nexport const CLIENT_CONDITIONS: readonly string[] = ['module', 'browser', 'development|production'];\nexport const SERVER_CONDITIONS: readonly string[] = ['module', 'node', 'development|production'];\n\n/**\n * Adds the `gyral-compiled` condition to an environment, on top of the app's conditions or\n * Vite's defaults: Vite replaces the defaults when a config names any condition.\n */\nfunction addCondition(\n name: string,\n config: EnvironmentOptions,\n env: ConfigEnv & { isSsrTargetWebworker?: boolean },\n): void {\n const consumer = config.consumer ?? (name === 'client' ? 'client' : 'server');\n const client = consumer === 'client' || env.isSsrTargetWebworker === true;\n const current = config.resolve?.conditions ?? (client ? CLIENT_CONDITIONS : SERVER_CONDITIONS);\n if (!current.includes(COMPILED_CONDITION)) {\n config.resolve = { ...config.resolve, conditions: [...current, COMPILED_CONDITION] };\n }\n}\n\n/**\n * The compiler's hooks. From core's TypeScript source (this workspace, `link:` checkouts) they\n * load through Vite's module runner, as a vite.config.ts would; from the published package,\n * with require.\n */\nasync function loadHooks(options: TemplateCompilerOptions): Promise<CompilerHooks> {\n const settings = {\n sources: options.sources ?? DEFAULT_TEMPLATE_SOURCES,\n parse5:\n options.parse5 === false\n ? undefined\n : typeof options.parse5 === 'string'\n ? options.parse5\n : 'parse5',\n };\n const require = createRequire(import.meta.url);\n if (!import.meta.url.endsWith('.ts')) {\n return (require('./compiler/hooks.js') as typeof import('./compiler/hooks.js')).createCompiler(\n settings,\n );\n }\n const { runnerImport } = require('vite') as typeof import('vite');\n const nodeEnv = process.env['NODE_ENV']; // the runner sets it when unset; the build owns it\n const { module } = await runnerImport<typeof import('./compiler/hooks.js')>(\n fileURLToPath(new URL('./compiler/hooks.ts', import.meta.url)),\n { configFile: false, logLevel: 'silent' },\n );\n if (nodeEnv === undefined) delete process.env['NODE_ENV'];\n else process.env['NODE_ENV'] = nodeEnv;\n return module.createCompiler(settings);\n}\n\n/** The template compiler alone (`gyralVitePreset()` includes it). */\nexport function gyralTemplateCompiler(options: TemplateCompilerOptions = {}): Plugin {\n let hooks: CompilerHooks | undefined;\n const ready = (): CompilerHooks => {\n if (hooks === undefined) throw new Error('gyral: the template compiler is not loaded yet');\n return hooks;\n };\n return {\n name: 'gyral:template-compiler',\n enforce: 'pre',\n apply: 'build',\n configEnvironment: addCondition,\n async configResolved(config) {\n hooks = await loadHooks(options);\n await hooks.configResolved.call(this, config);\n },\n buildStart(input) {\n return ready().buildStart.call(this, input);\n },\n transform: {\n filter: { id: /\\.[cm]?[jt]sx?$/, code: 'html' },\n handler(code, id, opts) {\n return ready().transform.call(this, code, id, opts);\n },\n },\n generateBundle(output, bundle, isWrite) {\n return ready().generateBundle.call(this, output, bundle, isWrite);\n },\n };\n}\n\n/** Gyral's packages: the dev server runs them through Vite, never Node (view/06). */\nexport const GYRAL_PACKAGES = /^@gyral\\//;\n\ntype Manifest = Partial<Record<'dependencies' | 'devDependencies' | 'peerDependencies', object>>;\n\nfunction manifest(file: string): Manifest | undefined {\n try {\n return JSON.parse(readFileSync(file, 'utf8')) as Manifest;\n } catch {\n return undefined;\n }\n}\n\n/** The installed manifest of `name`, looked up from `root` the way Node does (no exports map). */\nfunction installed(root: string, name: string): Manifest | undefined {\n for (let dir = root; ; dir = dirname(dir)) {\n const found = manifest(join(dir, 'node_modules', name, 'package.json'));\n if (found !== undefined || dirname(dir) === dir) return found;\n }\n}\n\n/**\n * The app's direct dependencies that depend on a Gyral package (a design system, say). They\n * import @gyral/core, so they must share the copy the dev server runs.\n */\nexport function gyralDependents(root: string): string[] {\n const app = manifest(join(root, 'package.json'));\n const names = Object.keys({ ...app?.dependencies, ...app?.devDependencies });\n return names.filter((name) => {\n if (GYRAL_PACKAGES.test(name)) return false;\n const dep = installed(root, name);\n return Object.keys({ ...dep?.dependencies, ...dep?.peerDependencies }).some((d) =>\n GYRAL_PACKAGES.test(d),\n );\n });\n}\n\n/**\n * Development output from the dev server's SSR (`ssrLoadModule`, view/06 \"Development\n * markers\"). Vite externalizes installed packages there and Node imports them itself, resolving\n * core's `#view-dev` without the `development` condition (Vite's `externalConditions` only pick\n * the entry file, not the package's own imports), so the server rendered production output.\n * In serve mode this plugin keeps Gyral's packages, and the app's dependencies that use them,\n * out of externalization in server environments: Vite resolves them with its conditions\n * (`development` in dev), and they all share one copy of core. `vite build` is unaffected.\n */\nexport function gyralDevServer(): Plugin {\n let root = process.cwd();\n return {\n name: 'gyral:dev-server',\n apply: 'serve',\n config(config) {\n root = resolve(config.root ?? process.cwd());\n },\n configEnvironment(name, config) {\n const consumer = config.consumer ?? (name === 'client' ? 'client' : 'server');\n if (consumer === 'client') return undefined;\n return { resolve: { noExternal: [GYRAL_PACKAGES, ...gyralDependents(root)] } };\n },\n };\n}\n\nexport interface GyralViteOptions {\n /** Modules to pre-bundle in dev, so Vite doesn't discover them mid-run and reload. */\n readonly optimize?: readonly string[];\n /** Template compiler options (`vite build` only). */\n readonly compiler?: TemplateCompilerOptions;\n}\n\nexport interface GyralViteConfig {\n readonly plugins: Plugin[];\n readonly resolve: { readonly dedupe: string[] };\n readonly optimizeDeps: { readonly include: string[] };\n}\n\n/**\n * Spread into a Vite config, or into each Vitest project:\n *\n * export default defineConfig({ ...gyralVitePreset(), build: { … } });\n *\n * With plugins of your own, list both: `plugins: [...preset.plugins, mine()]`.\n */\nexport function gyralVitePreset(options: GyralViteOptions = {}): GyralViteConfig {\n return {\n plugins: [gyralTemplateCompiler(options.compiler), gyralDevServer()],\n resolve: { dedupe: [] },\n optimizeDeps: { include: [...new Set(options.optimize ?? [])] },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gyral/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Gyral core: Model-View-Intent web components on
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Gyral core: Model-View-Intent web components on the web platform, with their own view layer. Inspired by Cycle.js.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"author": "
|
|
6
|
+
"author": "Mike Zupper",
|
|
7
7
|
"homepage": "https://github.com/gyraljs/gyral/tree/main/packages/core#readme",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -20,15 +20,35 @@
|
|
|
20
20
|
"types": "./dist/index.d.ts",
|
|
21
21
|
"default": "./dist/index.js"
|
|
22
22
|
},
|
|
23
|
+
"./server": {
|
|
24
|
+
"types": "./dist/server.d.ts",
|
|
25
|
+
"default": "./dist/server.js"
|
|
26
|
+
},
|
|
23
27
|
"./vite": {
|
|
24
28
|
"types": "./dist/vite.d.ts",
|
|
25
29
|
"default": "./dist/vite.js"
|
|
30
|
+
},
|
|
31
|
+
"./compiled": {
|
|
32
|
+
"types": "./dist/view/compiled.d.ts",
|
|
33
|
+
"default": "./dist/view/compiled.js"
|
|
34
|
+
},
|
|
35
|
+
"./eslint": {
|
|
36
|
+
"types": "./dist/eslint/index.d.ts",
|
|
37
|
+
"default": "./dist/eslint/index.js"
|
|
26
38
|
}
|
|
27
39
|
},
|
|
28
40
|
"imports": {
|
|
29
41
|
"#devtools": {
|
|
30
42
|
"development": "./dist/devtools.js",
|
|
31
43
|
"default": "./dist/devtools-off.js"
|
|
44
|
+
},
|
|
45
|
+
"#prepare": {
|
|
46
|
+
"gyral-compiled": "./dist/view/prepare-stub.js",
|
|
47
|
+
"default": "./dist/view/prepare.js"
|
|
48
|
+
},
|
|
49
|
+
"#view-dev": {
|
|
50
|
+
"development": "./dist/view/dev.js",
|
|
51
|
+
"default": "./dist/view/dev-off.js"
|
|
32
52
|
}
|
|
33
53
|
},
|
|
34
54
|
"files": [
|
|
@@ -39,14 +59,28 @@
|
|
|
39
59
|
"CHANGELOG.md"
|
|
40
60
|
],
|
|
41
61
|
"dependencies": {
|
|
42
|
-
"@standard-schema/spec": "1.1.0"
|
|
43
|
-
"effect": "3.22.2"
|
|
62
|
+
"@standard-schema/spec": "1.1.0"
|
|
44
63
|
},
|
|
45
64
|
"peerDependencies": {
|
|
46
|
-
"
|
|
65
|
+
"eslint": "^9.0.0 || ^10.0.0",
|
|
66
|
+
"parse5": "^7.0.0 || ^8.0.0",
|
|
67
|
+
"vite": "^8.0.0"
|
|
68
|
+
},
|
|
69
|
+
"peerDependenciesMeta": {
|
|
70
|
+
"eslint": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"parse5": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"vite": {
|
|
77
|
+
"optional": true
|
|
78
|
+
}
|
|
47
79
|
},
|
|
48
80
|
"devDependencies": {
|
|
49
|
-
"
|
|
81
|
+
"eslint": "10.12.0",
|
|
82
|
+
"parse5": "8.0.1",
|
|
83
|
+
"vite": "8.3.2"
|
|
50
84
|
},
|
|
51
85
|
"scripts": {
|
|
52
86
|
"build": "node ../../scripts/build-package.mjs"
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { ElementDirective } from './element-directive.js';
|
|
2
|
-
/** The element with `id`, searched from `from`'s own root outward to the document. */
|
|
3
|
-
export declare function findInScope(from: Element, id: string): Element | null;
|
|
4
|
-
/**
|
|
5
|
-
* Names the element after the element with `id`, even outside this component's shadow root:
|
|
6
|
-
*
|
|
7
|
-
* <form aria-label=${props.label} ${labelledBy('page-title')}>
|
|
8
|
-
*
|
|
9
|
-
* Uses `ariaLabelledByElements` (ARIA element reflection) where the browser has it, so the name
|
|
10
|
-
* stays in sync with the heading. Elsewhere it sets `aria-label` from `fallback`, or from the
|
|
11
|
-
* target's text. Element directives don't run on the server, so render a plain `aria-label` too
|
|
12
|
-
* (from a `label` prop) for the no-JS page: `aria-labelledby` wins over it once set.
|
|
13
|
-
*/
|
|
14
|
-
declare class LabelledBy extends ElementDirective<[id: string, fallback?: string]> {
|
|
15
|
-
#private;
|
|
16
|
-
apply(el: Element, [id, fallback]: [id: string, fallback?: string]): void;
|
|
17
|
-
}
|
|
18
|
-
export declare const labelledBy: (id: string, fallback?: string | undefined) => import("lit/directive.js").DirectiveResult<typeof LabelledBy>;
|
|
19
|
-
export {};
|
package/dist/accessible-name.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// Accessible names across shadow boundaries (gyral-czi.26). `aria-labelledby="page-title"` inside
|
|
2
|
-
// a shadow root can't see an id in the page, so a form or landmark in a component would be
|
|
3
|
-
// nameless. `labelledBy(id)` resolves the id outward through the shadow-including ancestors.
|
|
4
|
-
import { directive } from 'lit/directive.js';
|
|
5
|
-
import { ElementDirective } from './element-directive.js';
|
|
6
|
-
/** ARIA element reflection: newly available Baseline, so feature-detected (ADR 0003). */
|
|
7
|
-
const reflects = (el) => 'ariaLabelledByElements' in el;
|
|
8
|
-
/** The element with `id`, searched from `from`'s own root outward to the document. */
|
|
9
|
-
export function findInScope(from, id) {
|
|
10
|
-
for (let root = from.getRootNode();;) {
|
|
11
|
-
const found = 'getElementById' in root ? root.getElementById(id) : null;
|
|
12
|
-
if (found !== null && found !== from)
|
|
13
|
-
return found;
|
|
14
|
-
if (!(root instanceof ShadowRoot))
|
|
15
|
-
return null;
|
|
16
|
-
root = root.host.getRootNode();
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Names the element after the element with `id`, even outside this component's shadow root:
|
|
21
|
-
*
|
|
22
|
-
* <form aria-label=${props.label} ${labelledBy('page-title')}>
|
|
23
|
-
*
|
|
24
|
-
* Uses `ariaLabelledByElements` (ARIA element reflection) where the browser has it, so the name
|
|
25
|
-
* stays in sync with the heading. Elsewhere it sets `aria-label` from `fallback`, or from the
|
|
26
|
-
* target's text. Element directives don't run on the server, so render a plain `aria-label` too
|
|
27
|
-
* (from a `label` prop) for the no-JS page: `aria-labelledby` wins over it once set.
|
|
28
|
-
*/
|
|
29
|
-
class LabelledBy extends ElementDirective {
|
|
30
|
-
#applied = '';
|
|
31
|
-
apply(el, [id, fallback]) {
|
|
32
|
-
const key = `${id}\u0000${fallback ?? ''}`;
|
|
33
|
-
if (key === this.#applied)
|
|
34
|
-
return;
|
|
35
|
-
this.#applied = key;
|
|
36
|
-
// The labelling element may render after this one (a later sibling); try again once.
|
|
37
|
-
if (!this.#name(el, id, fallback)) {
|
|
38
|
-
queueMicrotask(() => {
|
|
39
|
-
this.#name(el, id, fallback);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
#name(el, id, fallback) {
|
|
44
|
-
const target = findInScope(el, id);
|
|
45
|
-
if (target !== null && reflects(el)) {
|
|
46
|
-
el.ariaLabelledByElements = [target];
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
const text = fallback ?? target?.textContent.trim() ?? '';
|
|
50
|
-
if (text !== '')
|
|
51
|
-
el.setAttribute('aria-label', text);
|
|
52
|
-
return target !== null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
export const labelledBy = directive(LabelledBy);
|
|
56
|
-
//# sourceMappingURL=accessible-name.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accessible-name.js","sourceRoot":"","sources":["../src/accessible-name.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,2FAA2F;AAC3F,6FAA6F;AAC7F,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAM1D,yFAAyF;AACzF,MAAM,QAAQ,GAAG,CAAC,EAAW,EAAoB,EAAE,CAAC,wBAAwB,IAAI,EAAE,CAAC;AAEnF,sFAAsF;AACtF,MAAM,UAAU,WAAW,CAAC,IAAa,EAAE,EAAU;IACnD,KAAK,IAAI,IAAI,GAAS,IAAI,CAAC,WAAW,EAAE,IAAK,CAAC;QAC5C,MAAM,KAAK,GAAG,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAE,IAAyB,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9F,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QACnD,IAAI,CAAC,CAAC,IAAI,YAAY,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,CAAC;AACH,CAAC;AAID;;;;;;;;;GASG;AACH,MAAM,UAAW,SAAQ,gBAAiD;IACxE,QAAQ,GAAG,EAAE,CAAC;IAEd,KAAK,CAAC,EAAW,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAkC;QAChE,MAAM,GAAG,GAAG,GAAG,EAAE,SAAS,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC3C,IAAI,GAAG,KAAK,IAAI,CAAC,QAAQ;YAAE,OAAO;QAClC,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;QACpB,qFAAqF;QACrF,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC;YAClC,cAAc,CAAC,GAAG,EAAE;gBAClB,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,EAAW,EAAE,EAAU,EAAE,QAA4B;QACzD,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,MAAM,KAAK,IAAI,IAAI,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YACpC,EAAE,CAAC,sBAAsB,GAAG,CAAC,MAAM,CAAC,CAAC;YACrC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,IAAI,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;QAC1D,IAAI,IAAI,KAAK,EAAE;YAAE,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QACrD,OAAO,MAAM,KAAK,IAAI,CAAC;IACzB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC","sourcesContent":["// Accessible names across shadow boundaries (gyral-czi.26). `aria-labelledby=\"page-title\"` inside\n// a shadow root can't see an id in the page, so a form or landmark in a component would be\n// nameless. `labelledBy(id)` resolves the id outward through the shadow-including ancestors.\nimport { directive } from 'lit/directive.js';\nimport { ElementDirective } from './element-directive.js';\n\ninterface Reflecting extends Element {\n ariaLabelledByElements: readonly Element[] | null;\n}\n\n/** ARIA element reflection: newly available Baseline, so feature-detected (ADR 0003). */\nconst reflects = (el: Element): el is Reflecting => 'ariaLabelledByElements' in el;\n\n/** The element with `id`, searched from `from`'s own root outward to the document. */\nexport function findInScope(from: Element, id: string): Element | null {\n for (let root: Node = from.getRootNode(); ;) {\n const found = 'getElementById' in root ? (root as DocumentOrShadow).getElementById(id) : null;\n if (found !== null && found !== from) return found;\n if (!(root instanceof ShadowRoot)) return null;\n root = root.host.getRootNode();\n }\n}\n\ntype DocumentOrShadow = Document | ShadowRoot;\n\n/**\n * Names the element after the element with `id`, even outside this component's shadow root:\n *\n * <form aria-label=${props.label} ${labelledBy('page-title')}>\n *\n * Uses `ariaLabelledByElements` (ARIA element reflection) where the browser has it, so the name\n * stays in sync with the heading. Elsewhere it sets `aria-label` from `fallback`, or from the\n * target's text. Element directives don't run on the server, so render a plain `aria-label` too\n * (from a `label` prop) for the no-JS page: `aria-labelledby` wins over it once set.\n */\nclass LabelledBy extends ElementDirective<[id: string, fallback?: string]> {\n #applied = '';\n\n apply(el: Element, [id, fallback]: [id: string, fallback?: string]): void {\n const key = `${id}\\u0000${fallback ?? ''}`;\n if (key === this.#applied) return;\n this.#applied = key;\n // The labelling element may render after this one (a later sibling); try again once.\n if (!this.#name(el, id, fallback)) {\n queueMicrotask(() => {\n this.#name(el, id, fallback);\n });\n }\n }\n\n #name(el: Element, id: string, fallback: string | undefined): boolean {\n const target = findInScope(el, id);\n if (target !== null && reflects(el)) {\n el.ariaLabelledByElements = [target];\n return true;\n }\n const text = fallback ?? target?.textContent.trim() ?? '';\n if (text !== '') el.setAttribute('aria-label', text);\n return target !== null;\n }\n}\n\nexport const labelledBy = directive(LabelledBy);\n"]}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { nothing } from 'lit';
|
|
2
|
-
import { Directive, type ElementPart, type PartInfo } from 'lit/directive.js';
|
|
3
|
-
/**
|
|
4
|
-
* Base for element directives (`<input ${invalid(errors)}>`): they act on the element they are
|
|
5
|
-
* placed on and render nothing. Subclasses declare their arguments as `Args` and implement
|
|
6
|
-
* `apply`. Wrap the class with `directive()` (re-exported from core) to get the template
|
|
7
|
-
* function. Element parts are not rendered on the server, so `apply` only runs in the browser.
|
|
8
|
-
*
|
|
9
|
-
* class Focus extends ElementDirective<[when: boolean]> {
|
|
10
|
-
* apply(el: Element, [when]: [boolean]) { if (when && el instanceof HTMLElement) el.focus(); }
|
|
11
|
-
* }
|
|
12
|
-
* export const focusWhen = directive(Focus);
|
|
13
|
-
*/
|
|
14
|
-
export declare abstract class ElementDirective<Args extends unknown[]> extends Directive {
|
|
15
|
-
constructor(info: PartInfo);
|
|
16
|
-
/** Called on every render with the directive's current arguments. */
|
|
17
|
-
abstract apply(element: Element, args: Args): void;
|
|
18
|
-
render(...args: Args): typeof nothing;
|
|
19
|
-
update(part: ElementPart, args: Args): typeof nothing;
|
|
20
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { nothing } from 'lit';
|
|
2
|
-
import { Directive, PartType } from 'lit/directive.js';
|
|
3
|
-
/**
|
|
4
|
-
* Base for element directives (`<input ${invalid(errors)}>`): they act on the element they are
|
|
5
|
-
* placed on and render nothing. Subclasses declare their arguments as `Args` and implement
|
|
6
|
-
* `apply`. Wrap the class with `directive()` (re-exported from core) to get the template
|
|
7
|
-
* function. Element parts are not rendered on the server, so `apply` only runs in the browser.
|
|
8
|
-
*
|
|
9
|
-
* class Focus extends ElementDirective<[when: boolean]> {
|
|
10
|
-
* apply(el: Element, [when]: [boolean]) { if (when && el instanceof HTMLElement) el.focus(); }
|
|
11
|
-
* }
|
|
12
|
-
* export const focusWhen = directive(Focus);
|
|
13
|
-
*/
|
|
14
|
-
export class ElementDirective extends Directive {
|
|
15
|
-
constructor(info) {
|
|
16
|
-
super(info);
|
|
17
|
-
if (info.type !== PartType.ELEMENT) {
|
|
18
|
-
throw new Error(`${new.target.name} must be used on an element: <el \${directive(…)}>`);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
// Lit reads the directive's arguments from render(); update() does the work.
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
23
|
-
render(...args) {
|
|
24
|
-
return nothing;
|
|
25
|
-
}
|
|
26
|
-
update(part, args) {
|
|
27
|
-
this.apply(part.element, args);
|
|
28
|
-
return nothing;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=element-directive.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"element-directive.js","sourceRoot":"","sources":["../src/element-directive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAmC,MAAM,kBAAkB,CAAC;AAExF;;;;;;;;;;GAUG;AACH,MAAM,OAAgB,gBAAyC,SAAQ,SAAS;IAC9E,YAAY,IAAc;QACxB,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,oDAAoD,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAKD,6EAA6E;IAC7E,6DAA6D;IACpD,MAAM,CAAC,GAAG,IAAU;QAC3B,OAAO,OAAO,CAAC;IACjB,CAAC;IAEQ,MAAM,CAAC,IAAiB,EAAE,IAAU;QAC3C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC/B,OAAO,OAAO,CAAC;IACjB,CAAC;CACF","sourcesContent":["import { nothing } from 'lit';\nimport { Directive, PartType, type ElementPart, type PartInfo } from 'lit/directive.js';\n\n/**\n * Base for element directives (`<input ${invalid(errors)}>`): they act on the element they are\n * placed on and render nothing. Subclasses declare their arguments as `Args` and implement\n * `apply`. Wrap the class with `directive()` (re-exported from core) to get the template\n * function. Element parts are not rendered on the server, so `apply` only runs in the browser.\n *\n * class Focus extends ElementDirective<[when: boolean]> {\n * apply(el: Element, [when]: [boolean]) { if (when && el instanceof HTMLElement) el.focus(); }\n * }\n * export const focusWhen = directive(Focus);\n */\nexport abstract class ElementDirective<Args extends unknown[]> extends Directive {\n constructor(info: PartInfo) {\n super(info);\n if (info.type !== PartType.ELEMENT) {\n throw new Error(`${new.target.name} must be used on an element: <el \\${directive(…)}>`);\n }\n }\n\n /** Called on every render with the directive's current arguments. */\n abstract apply(element: Element, args: Args): void;\n\n // Lit reads the directive's arguments from render(); update() does the work.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n override render(...args: Args): typeof nothing {\n return nothing;\n }\n\n override update(part: ElementPart, args: Args): typeof nothing {\n this.apply(part.element, args);\n return nothing;\n }\n}\n"]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Effect, type Fiber } from 'effect';
|
|
2
|
-
/**
|
|
3
|
-
* The single place Gyral starts Effect programs (ADR 0006). There are no services to
|
|
4
|
-
* provide yet, so the default runtime is enough; a ManagedRuntime with layers goes here
|
|
5
|
-
* when drivers need shared resources.
|
|
6
|
-
*/
|
|
7
|
-
export declare const fork: <A>(program: Effect.Effect<A>) => Fiber.RuntimeFiber<A>;
|
package/dist/internal/runtime.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Effect } from 'effect';
|
|
2
|
-
/**
|
|
3
|
-
* The single place Gyral starts Effect programs (ADR 0006). There are no services to
|
|
4
|
-
* provide yet, so the default runtime is enough; a ManagedRuntime with layers goes here
|
|
5
|
-
* when drivers need shared resources.
|
|
6
|
-
*/
|
|
7
|
-
export const fork = (program) => Effect.runFork(program);
|
|
8
|
-
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/internal/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAE5C;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAI,OAAyB,EAAyB,EAAE,CAC1E,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC","sourcesContent":["import { Effect, type Fiber } from 'effect';\n\n/**\n * The single place Gyral starts Effect programs (ADR 0006). There are no services to\n * provide yet, so the default runtime is enough; a ManagedRuntime with layers goes here\n * when drivers need shared resources.\n */\nexport const fork = <A>(program: Effect.Effect<A>): Fiber.RuntimeFiber<A> =>\n Effect.runFork(program);\n"]}
|
package/dist/invalid.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { ElementDirective } from './element-directive.js';
|
|
2
|
-
type Errors = readonly string[] | string | undefined;
|
|
3
|
-
/**
|
|
4
|
-
* Mirrors model errors to native validity (ADR 0008): sets `setCustomValidity` and
|
|
5
|
-
* `aria-invalid`, so `:user-invalid` and native bubbles agree with the model.
|
|
6
|
-
*
|
|
7
|
-
* The custom error clears when:
|
|
8
|
-
* - the control fires `input` or `change` (the user edited it);
|
|
9
|
-
* - the bound errors become `undefined` or empty (the model cleared them);
|
|
10
|
-
* - a submit finds the error stale: the value changed without an event (set from code, e.g.
|
|
11
|
-
* by a test or a script). Then the error is dropped and the form is submitted again once.
|
|
12
|
-
*
|
|
13
|
-
* An error is applied again only when a new value arrives (keep `fieldErrors()` results in
|
|
14
|
-
* state). Element parts don't render on the server, so this only runs in the browser.
|
|
15
|
-
*/
|
|
16
|
-
declare class InvalidDirective extends ElementDirective<[errors?: Errors]> {
|
|
17
|
-
#private;
|
|
18
|
-
apply(el: Element, [errors]: [errors?: Errors]): void;
|
|
19
|
-
}
|
|
20
|
-
export declare const invalid: (errors?: Errors) => import("lit/directive.js").DirectiveResult<typeof InvalidDirective>;
|
|
21
|
-
export {};
|
package/dist/invalid.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { directive } from 'lit/directive.js';
|
|
2
|
-
import { ElementDirective } from './element-directive.js';
|
|
3
|
-
const isValidatable = (el) => 'setCustomValidity' in el;
|
|
4
|
-
const valueOf = (el) => ('value' in el ? el.value : undefined);
|
|
5
|
-
const formOf = (el) => {
|
|
6
|
-
const form = 'form' in el ? el.form : undefined;
|
|
7
|
-
return form instanceof HTMLFormElement ? form : undefined;
|
|
8
|
-
};
|
|
9
|
-
// Forms with a resubmit already queued: several stale fields in one validation pass resubmit once.
|
|
10
|
-
const resubmitting = new WeakSet();
|
|
11
|
-
/**
|
|
12
|
-
* Mirrors model errors to native validity (ADR 0008): sets `setCustomValidity` and
|
|
13
|
-
* `aria-invalid`, so `:user-invalid` and native bubbles agree with the model.
|
|
14
|
-
*
|
|
15
|
-
* The custom error clears when:
|
|
16
|
-
* - the control fires `input` or `change` (the user edited it);
|
|
17
|
-
* - the bound errors become `undefined` or empty (the model cleared them);
|
|
18
|
-
* - a submit finds the error stale: the value changed without an event (set from code, e.g.
|
|
19
|
-
* by a test or a script). Then the error is dropped and the form is submitted again once.
|
|
20
|
-
*
|
|
21
|
-
* An error is applied again only when a new value arrives (keep `fieldErrors()` results in
|
|
22
|
-
* state). Element parts don't render on the server, so this only runs in the browser.
|
|
23
|
-
*/
|
|
24
|
-
class InvalidDirective extends ElementDirective {
|
|
25
|
-
#last;
|
|
26
|
-
#listening;
|
|
27
|
-
apply(el, [errors]) {
|
|
28
|
-
if (errors === this.#last)
|
|
29
|
-
return;
|
|
30
|
-
this.#last = errors;
|
|
31
|
-
this.#listening?.abort();
|
|
32
|
-
this.#listening = undefined;
|
|
33
|
-
const message = typeof errors === 'string' ? errors : (errors ?? []).join(' ');
|
|
34
|
-
if (isValidatable(el))
|
|
35
|
-
el.setCustomValidity(message);
|
|
36
|
-
if (message === '') {
|
|
37
|
-
el.removeAttribute('aria-invalid');
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
el.setAttribute('aria-invalid', 'true');
|
|
41
|
-
const listening = new AbortController();
|
|
42
|
-
this.#listening = listening;
|
|
43
|
-
const { signal } = listening;
|
|
44
|
-
const rejectedValue = valueOf(el);
|
|
45
|
-
const clear = () => {
|
|
46
|
-
listening.abort();
|
|
47
|
-
if (isValidatable(el))
|
|
48
|
-
el.setCustomValidity('');
|
|
49
|
-
el.removeAttribute('aria-invalid');
|
|
50
|
-
};
|
|
51
|
-
el.addEventListener('input', clear, { signal });
|
|
52
|
-
el.addEventListener('change', clear, { signal });
|
|
53
|
-
el.addEventListener('invalid', (event) => {
|
|
54
|
-
if (Object.is(valueOf(el), rejectedValue))
|
|
55
|
-
return; // still the rejected value
|
|
56
|
-
event.preventDefault(); // no bubble for an error that no longer applies
|
|
57
|
-
clear();
|
|
58
|
-
const form = formOf(el);
|
|
59
|
-
if (form === undefined || resubmitting.has(form))
|
|
60
|
-
return;
|
|
61
|
-
resubmitting.add(form);
|
|
62
|
-
queueMicrotask(() => {
|
|
63
|
-
resubmitting.delete(form);
|
|
64
|
-
form.requestSubmit();
|
|
65
|
-
});
|
|
66
|
-
}, { signal });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
export const invalid = directive(InvalidDirective);
|
|
70
|
-
//# sourceMappingURL=invalid.js.map
|
package/dist/invalid.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"invalid.js","sourceRoot":"","sources":["../src/invalid.ts"],"names":[],"mappings":"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","sourcesContent":["import { directive } from 'lit/directive.js';\nimport { ElementDirective } from './element-directive.js';\n\ntype Errors = readonly string[] | string | undefined;\n\ninterface Validatable extends Element {\n setCustomValidity(message: string): void;\n}\n\nconst isValidatable = (el: Element): el is Validatable => 'setCustomValidity' in el;\n\nconst valueOf = (el: Element): unknown => ('value' in el ? el.value : undefined);\n\nconst formOf = (el: Element): HTMLFormElement | undefined => {\n const form = 'form' in el ? el.form : undefined;\n return form instanceof HTMLFormElement ? form : undefined;\n};\n\n// Forms with a resubmit already queued: several stale fields in one validation pass resubmit once.\nconst resubmitting = new WeakSet<HTMLFormElement>();\n\n/**\n * Mirrors model errors to native validity (ADR 0008): sets `setCustomValidity` and\n * `aria-invalid`, so `:user-invalid` and native bubbles agree with the model.\n *\n * The custom error clears when:\n * - the control fires `input` or `change` (the user edited it);\n * - the bound errors become `undefined` or empty (the model cleared them);\n * - a submit finds the error stale: the value changed without an event (set from code, e.g.\n * by a test or a script). Then the error is dropped and the form is submitted again once.\n *\n * An error is applied again only when a new value arrives (keep `fieldErrors()` results in\n * state). Element parts don't render on the server, so this only runs in the browser.\n */\nclass InvalidDirective extends ElementDirective<[errors?: Errors]> {\n #last: Errors;\n #listening: AbortController | undefined;\n\n apply(el: Element, [errors]: [errors?: Errors]): void {\n if (errors === this.#last) return;\n this.#last = errors;\n this.#listening?.abort();\n this.#listening = undefined;\n const message = typeof errors === 'string' ? errors : (errors ?? []).join(' ');\n if (isValidatable(el)) el.setCustomValidity(message);\n if (message === '') {\n el.removeAttribute('aria-invalid');\n return;\n }\n el.setAttribute('aria-invalid', 'true');\n\n const listening = new AbortController();\n this.#listening = listening;\n const { signal } = listening;\n const rejectedValue = valueOf(el);\n const clear = (): void => {\n listening.abort();\n if (isValidatable(el)) el.setCustomValidity('');\n el.removeAttribute('aria-invalid');\n };\n el.addEventListener('input', clear, { signal });\n el.addEventListener('change', clear, { signal });\n el.addEventListener(\n 'invalid',\n (event) => {\n if (Object.is(valueOf(el), rejectedValue)) return; // still the rejected value\n event.preventDefault(); // no bubble for an error that no longer applies\n clear();\n const form = formOf(el);\n if (form === undefined || resubmitting.has(form)) return;\n resubmitting.add(form);\n queueMicrotask(() => {\n resubmitting.delete(form);\n form.requestSubmit();\n });\n },\n { signal },\n );\n }\n}\n\nexport const invalid = directive(InvalidDirective);\n"]}
|
package/dist/live-boolean.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Directive, type AttributePart, type PartInfo } from 'lit/directive.js';
|
|
2
|
-
/**
|
|
3
|
-
* A boolean that is right both in server-rendered markup and in the live DOM (ADR 0012).
|
|
4
|
-
* Use it in a boolean attribute binding:
|
|
5
|
-
*
|
|
6
|
-
* <input type="checkbox" ?checked=${liveBoolean(s.on)} />
|
|
7
|
-
* <option ?selected=${liveBoolean(s.sort === 'price')}>Price</option>
|
|
8
|
-
*
|
|
9
|
-
* - On the server it renders the attribute when true and omits it when false.
|
|
10
|
-
* (A property binding, `.checked=${false}`, is serialized by Lit SSR as `checked="false"`,
|
|
11
|
-
* which *checks* the box. Never bind boolean form state as a property in SSR'd views.)
|
|
12
|
-
* - In the browser it also sets the element's property of the same name (`checked`,
|
|
13
|
-
* `selected`, `open`, …), so the control follows model state even after the user has
|
|
14
|
-
* changed it. The attribute alone stops controlling `checked` once a box has been clicked.
|
|
15
|
-
*/
|
|
16
|
-
declare class LiveBoolean extends Directive {
|
|
17
|
-
constructor(info: PartInfo);
|
|
18
|
-
render(value: boolean): boolean;
|
|
19
|
-
update(part: AttributePart, [value]: [boolean]): boolean;
|
|
20
|
-
}
|
|
21
|
-
export declare const liveBoolean: (value: boolean) => import("lit/directive.js").DirectiveResult<typeof LiveBoolean>;
|
|
22
|
-
export {};
|