@bquery/bquery 1.5.0 → 1.7.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/README.md +193 -23
- package/dist/a11y/announce.d.ts +43 -0
- package/dist/a11y/announce.d.ts.map +1 -0
- package/dist/a11y/audit.d.ts +42 -0
- package/dist/a11y/audit.d.ts.map +1 -0
- package/dist/a11y/index.d.ts +53 -0
- package/dist/a11y/index.d.ts.map +1 -0
- package/dist/a11y/media-preferences.d.ts +77 -0
- package/dist/a11y/media-preferences.d.ts.map +1 -0
- package/dist/a11y/roving-tab-index.d.ts +38 -0
- package/dist/a11y/roving-tab-index.d.ts.map +1 -0
- package/dist/a11y/skip-link.d.ts +37 -0
- package/dist/a11y/skip-link.d.ts.map +1 -0
- package/dist/a11y/trap-focus.d.ts +49 -0
- package/dist/a11y/trap-focus.d.ts.map +1 -0
- package/dist/a11y/types.d.ts +152 -0
- package/dist/a11y/types.d.ts.map +1 -0
- package/dist/a11y-C5QOVvRn.js +421 -0
- package/dist/a11y-C5QOVvRn.js.map +1 -0
- package/dist/a11y.es.mjs +14 -0
- package/dist/component/component.d.ts +13 -5
- package/dist/component/component.d.ts.map +1 -1
- package/dist/component/html.d.ts +40 -3
- package/dist/component/html.d.ts.map +1 -1
- package/dist/component/index.d.ts +3 -2
- package/dist/component/index.d.ts.map +1 -1
- package/dist/component/library.d.ts.map +1 -1
- package/dist/component/scope.d.ts +138 -0
- package/dist/component/scope.d.ts.map +1 -0
- package/dist/component/types.d.ts +184 -17
- package/dist/component/types.d.ts.map +1 -1
- package/dist/component-CuuTijA6.js +684 -0
- package/dist/component-CuuTijA6.js.map +1 -0
- package/dist/component.es.mjs +10 -6
- package/dist/{config-DRmZZno3.js → config-BW35FKuA.js} +4 -4
- package/dist/config-BW35FKuA.js.map +1 -0
- package/dist/constraints-3lV9yyBw.js +100 -0
- package/dist/constraints-3lV9yyBw.js.map +1 -0
- package/dist/core/collection.d.ts +48 -0
- package/dist/core/collection.d.ts.map +1 -1
- package/dist/core/element.d.ts +92 -0
- package/dist/core/element.d.ts.map +1 -1
- package/dist/core/env.d.ts +18 -0
- package/dist/core/env.d.ts.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/shared.d.ts +8 -0
- package/dist/core/shared.d.ts.map +1 -1
- package/dist/core/utils/index.d.ts +52 -41
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core-Cjl7GUu8.js +717 -0
- package/dist/core-Cjl7GUu8.js.map +1 -0
- package/dist/{core-DPdbItcq.js → core-DnlyjbF2.js} +1 -1
- package/dist/{core-DPdbItcq.js.map → core-DnlyjbF2.js.map} +1 -1
- package/dist/core.es.mjs +45 -44
- package/dist/custom-directives-7wAShnnd.js +9 -0
- package/dist/custom-directives-7wAShnnd.js.map +1 -0
- package/dist/devtools/devtools.d.ts +212 -0
- package/dist/devtools/devtools.d.ts.map +1 -0
- package/dist/devtools/index.d.ts +20 -0
- package/dist/devtools/index.d.ts.map +1 -0
- package/dist/devtools/types.d.ts +69 -0
- package/dist/devtools/types.d.ts.map +1 -0
- package/dist/devtools-D2fQLhDN.js +122 -0
- package/dist/devtools-D2fQLhDN.js.map +1 -0
- package/dist/devtools.es.mjs +19 -0
- package/dist/dnd/draggable.d.ts +51 -0
- package/dist/dnd/draggable.d.ts.map +1 -0
- package/dist/dnd/droppable.d.ts +38 -0
- package/dist/dnd/droppable.d.ts.map +1 -0
- package/dist/dnd/index.d.ts +47 -0
- package/dist/dnd/index.d.ts.map +1 -0
- package/dist/dnd/sortable.d.ts +43 -0
- package/dist/dnd/sortable.d.ts.map +1 -0
- package/dist/dnd/types.d.ts +250 -0
- package/dist/dnd/types.d.ts.map +1 -0
- package/dist/dnd-B8EgyzaI.js +244 -0
- package/dist/dnd-B8EgyzaI.js.map +1 -0
- package/dist/dnd.es.mjs +6 -0
- package/dist/env-NeVmr4Gf.js +19 -0
- package/dist/env-NeVmr4Gf.js.map +1 -0
- package/dist/forms/create-form.d.ts +49 -0
- package/dist/forms/create-form.d.ts.map +1 -0
- package/dist/forms/index.d.ts +39 -0
- package/dist/forms/index.d.ts.map +1 -0
- package/dist/forms/types.d.ts +139 -0
- package/dist/forms/types.d.ts.map +1 -0
- package/dist/forms/validators.d.ts +179 -0
- package/dist/forms/validators.d.ts.map +1 -0
- package/dist/forms-C3yovgH9.js +141 -0
- package/dist/forms-C3yovgH9.js.map +1 -0
- package/dist/forms.es.mjs +14 -0
- package/dist/full.d.ts +37 -9
- package/dist/full.d.ts.map +1 -1
- package/dist/full.es.mjs +186 -91
- package/dist/full.iife.js +47 -31
- package/dist/full.iife.js.map +1 -1
- package/dist/full.umd.js +47 -31
- package/dist/full.umd.js.map +1 -1
- package/dist/i18n/formatting.d.ts +40 -0
- package/dist/i18n/formatting.d.ts.map +1 -0
- package/dist/i18n/i18n.d.ts +48 -0
- package/dist/i18n/i18n.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +57 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/translate.d.ts +83 -0
- package/dist/i18n/translate.d.ts.map +1 -0
- package/dist/i18n/types.d.ts +156 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n-BnnhTFOS.js +89 -0
- package/dist/i18n-BnnhTFOS.js.map +1 -0
- package/dist/i18n.es.mjs +6 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.mjs +233 -138
- package/dist/media/battery.d.ts +35 -0
- package/dist/media/battery.d.ts.map +1 -0
- package/dist/media/breakpoints.d.ts +51 -0
- package/dist/media/breakpoints.d.ts.map +1 -0
- package/dist/media/clipboard.d.ts +30 -0
- package/dist/media/clipboard.d.ts.map +1 -0
- package/dist/media/device-sensors.d.ts +54 -0
- package/dist/media/device-sensors.d.ts.map +1 -0
- package/dist/media/geolocation.d.ts +38 -0
- package/dist/media/geolocation.d.ts.map +1 -0
- package/dist/media/index.d.ts +42 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/media-query.d.ts +36 -0
- package/dist/media/media-query.d.ts.map +1 -0
- package/dist/media/network.d.ts +35 -0
- package/dist/media/network.d.ts.map +1 -0
- package/dist/media/types.d.ts +173 -0
- package/dist/media/types.d.ts.map +1 -0
- package/dist/media/viewport.d.ts +32 -0
- package/dist/media/viewport.d.ts.map +1 -0
- package/dist/media-Di2Ta22s.js +340 -0
- package/dist/media-Di2Ta22s.js.map +1 -0
- package/dist/media.es.mjs +12 -0
- package/dist/motion/index.d.ts +7 -3
- package/dist/motion/index.d.ts.map +1 -1
- package/dist/motion/morph.d.ts +27 -0
- package/dist/motion/morph.d.ts.map +1 -0
- package/dist/motion/parallax.d.ts +30 -0
- package/dist/motion/parallax.d.ts.map +1 -0
- package/dist/motion/reduced-motion.d.ts +36 -3
- package/dist/motion/reduced-motion.d.ts.map +1 -1
- package/dist/motion/types.d.ts +58 -0
- package/dist/motion/types.d.ts.map +1 -1
- package/dist/motion/typewriter.d.ts +31 -0
- package/dist/motion/typewriter.d.ts.map +1 -0
- package/dist/motion-qPj_TYGv.js +530 -0
- package/dist/motion-qPj_TYGv.js.map +1 -0
- package/dist/motion.es.mjs +27 -23
- package/dist/mount-SM07RUa6.js +403 -0
- package/dist/mount-SM07RUa6.js.map +1 -0
- package/dist/{object-qGpWr6-J.js → object-BCk-1c8T.js} +5 -4
- package/dist/{object-qGpWr6-J.js.map → object-BCk-1c8T.js.map} +1 -1
- package/dist/{platform-B7JhGBc7.js → platform-CPbCprb6.js} +3 -3
- package/dist/platform-CPbCprb6.js.map +1 -0
- package/dist/platform.es.mjs +2 -2
- package/dist/plugin/index.d.ts +22 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/registry.d.ts +108 -0
- package/dist/plugin/registry.d.ts.map +1 -0
- package/dist/plugin/types.d.ts +110 -0
- package/dist/plugin/types.d.ts.map +1 -0
- package/dist/plugin-cPoOHFLY.js +64 -0
- package/dist/plugin-cPoOHFLY.js.map +1 -0
- package/dist/plugin.es.mjs +9 -0
- package/dist/reactive/computed.d.ts +7 -0
- package/dist/reactive/computed.d.ts.map +1 -1
- package/dist/reactive-Cfv0RK6x.js +233 -0
- package/dist/reactive-Cfv0RK6x.js.map +1 -0
- package/dist/reactive.es.mjs +18 -17
- package/dist/registry-CWf368tT.js +26 -0
- package/dist/registry-CWf368tT.js.map +1 -0
- package/dist/router/bq-link.d.ts +112 -0
- package/dist/router/bq-link.d.ts.map +1 -0
- package/dist/router/constraints.d.ts +9 -0
- package/dist/router/constraints.d.ts.map +1 -0
- package/dist/router/index.d.ts +14 -6
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/match.d.ts +0 -1
- package/dist/router/match.d.ts.map +1 -1
- package/dist/router/path-pattern.d.ts +14 -0
- package/dist/router/path-pattern.d.ts.map +1 -0
- package/dist/router/query.d.ts.map +1 -1
- package/dist/router/router.d.ts +3 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/types.d.ts +48 -4
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/use-route.d.ts +50 -0
- package/dist/router/use-route.d.ts.map +1 -0
- package/dist/router/utils.d.ts +3 -0
- package/dist/router/utils.d.ts.map +1 -1
- package/dist/router-BrthaP_z.js +473 -0
- package/dist/router-BrthaP_z.js.map +1 -0
- package/dist/router.es.mjs +13 -10
- package/dist/{sanitize-jyJ2ryE2.js → sanitize-B1V4JswB.js} +95 -83
- package/dist/sanitize-B1V4JswB.js.map +1 -0
- package/dist/security/index.d.ts +2 -0
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/sanitize.d.ts +4 -1
- package/dist/security/sanitize.d.ts.map +1 -1
- package/dist/security/trusted-html.d.ts +53 -0
- package/dist/security/trusted-html.d.ts.map +1 -0
- package/dist/security.es.mjs +10 -9
- package/dist/ssr/hydrate.d.ts +65 -0
- package/dist/ssr/hydrate.d.ts.map +1 -0
- package/dist/ssr/index.d.ts +59 -0
- package/dist/ssr/index.d.ts.map +1 -0
- package/dist/ssr/render.d.ts +62 -0
- package/dist/ssr/render.d.ts.map +1 -0
- package/dist/ssr/serialize.d.ts +118 -0
- package/dist/ssr/serialize.d.ts.map +1 -0
- package/dist/ssr/types.d.ts +70 -0
- package/dist/ssr/types.d.ts.map +1 -0
- package/dist/ssr-B2qd_WBB.js +248 -0
- package/dist/ssr-B2qd_WBB.js.map +1 -0
- package/dist/ssr.es.mjs +9 -0
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/define-store.d.ts +1 -1
- package/dist/store/define-store.d.ts.map +1 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/mapping.d.ts +1 -1
- package/dist/store/mapping.d.ts.map +1 -1
- package/dist/store/persisted.d.ts +38 -4
- package/dist/store/persisted.d.ts.map +1 -1
- package/dist/store/types.d.ts +140 -3
- package/dist/store/types.d.ts.map +1 -1
- package/dist/store/utils.d.ts +2 -2
- package/dist/store/utils.d.ts.map +1 -1
- package/dist/store/watch.d.ts +1 -1
- package/dist/store/watch.d.ts.map +1 -1
- package/dist/store-DWpyH6p5.js +338 -0
- package/dist/store-DWpyH6p5.js.map +1 -0
- package/dist/store.es.mjs +11 -10
- package/dist/storybook/index.d.ts +37 -0
- package/dist/storybook/index.d.ts.map +1 -0
- package/dist/storybook.es.mjs +151 -0
- package/dist/storybook.es.mjs.map +1 -0
- package/dist/testing/index.d.ts +23 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/testing.d.ts +156 -0
- package/dist/testing/testing.d.ts.map +1 -0
- package/dist/testing/types.d.ts +134 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing-CsqjNUyy.js +224 -0
- package/dist/testing-CsqjNUyy.js.map +1 -0
- package/dist/testing.es.mjs +9 -0
- package/dist/type-guards-Do9DWgNp.js +44 -0
- package/dist/type-guards-Do9DWgNp.js.map +1 -0
- package/dist/untrack-DJVQQ2WM.js +33 -0
- package/dist/untrack-DJVQQ2WM.js.map +1 -0
- package/dist/view/custom-directives.d.ts +20 -0
- package/dist/view/custom-directives.d.ts.map +1 -0
- package/dist/view/evaluate.d.ts.map +1 -1
- package/dist/view/process.d.ts.map +1 -1
- package/dist/view.es.mjs +11 -10
- package/package.json +52 -11
- package/src/a11y/announce.ts +131 -0
- package/src/a11y/audit.ts +314 -0
- package/src/a11y/index.ts +68 -0
- package/src/a11y/media-preferences.ts +255 -0
- package/src/a11y/roving-tab-index.ts +164 -0
- package/src/a11y/skip-link.ts +255 -0
- package/src/a11y/trap-focus.ts +184 -0
- package/src/a11y/types.ts +183 -0
- package/src/component/component.ts +345 -65
- package/src/component/html.ts +153 -53
- package/src/component/index.ts +12 -2
- package/src/component/library.ts +66 -28
- package/src/component/scope.ts +212 -0
- package/src/component/types.ts +238 -19
- package/src/core/collection.ts +707 -628
- package/src/core/element.ts +981 -774
- package/src/core/env.ts +60 -0
- package/src/core/index.ts +49 -48
- package/src/core/shared.ts +62 -13
- package/src/core/utils/index.ts +148 -83
- package/src/devtools/devtools.ts +410 -0
- package/src/devtools/index.ts +48 -0
- package/src/devtools/types.ts +104 -0
- package/src/dnd/draggable.ts +296 -0
- package/src/dnd/droppable.ts +228 -0
- package/src/dnd/index.ts +62 -0
- package/src/dnd/sortable.ts +307 -0
- package/src/dnd/types.ts +293 -0
- package/src/forms/create-form.ts +278 -0
- package/src/forms/index.ts +65 -0
- package/src/forms/types.ts +154 -0
- package/src/forms/validators.ts +265 -0
- package/src/full.ts +260 -3
- package/src/i18n/formatting.ts +67 -0
- package/src/i18n/i18n.ts +200 -0
- package/src/i18n/index.ts +67 -0
- package/src/i18n/translate.ts +182 -0
- package/src/i18n/types.ts +171 -0
- package/src/index.ts +108 -36
- package/src/media/battery.ts +116 -0
- package/src/media/breakpoints.ts +131 -0
- package/src/media/clipboard.ts +80 -0
- package/src/media/device-sensors.ts +158 -0
- package/src/media/geolocation.ts +119 -0
- package/src/media/index.ts +76 -0
- package/src/media/media-query.ts +92 -0
- package/src/media/network.ts +115 -0
- package/src/media/types.ts +177 -0
- package/src/media/viewport.ts +84 -0
- package/src/motion/index.ts +57 -48
- package/src/motion/morph.ts +151 -0
- package/src/motion/parallax.ts +120 -0
- package/src/motion/reduced-motion.ts +66 -17
- package/src/motion/transition.ts +97 -97
- package/src/motion/types.ts +63 -0
- package/src/motion/typewriter.ts +164 -0
- package/src/platform/announcer.ts +208 -208
- package/src/platform/config.ts +163 -163
- package/src/platform/cookies.ts +165 -165
- package/src/platform/index.ts +39 -39
- package/src/platform/meta.ts +168 -168
- package/src/plugin/index.ts +37 -0
- package/src/plugin/registry.ts +269 -0
- package/src/plugin/types.ts +137 -0
- package/src/reactive/async-data.ts +486 -486
- package/src/reactive/computed.ts +130 -92
- package/src/reactive/index.ts +37 -37
- package/src/reactive/signal.ts +29 -29
- package/src/router/bq-link.ts +279 -0
- package/src/router/constraints.ts +201 -0
- package/src/router/index.ts +49 -41
- package/src/router/match.ts +312 -106
- package/src/router/path-pattern.ts +52 -0
- package/src/router/query.ts +38 -35
- package/src/router/router.ts +402 -211
- package/src/router/types.ts +139 -93
- package/src/router/use-route.ts +68 -0
- package/src/router/utils.ts +157 -116
- package/src/security/constants.ts +211 -211
- package/src/security/index.ts +12 -10
- package/src/security/sanitize.ts +6 -2
- package/src/security/trusted-html.ts +71 -0
- package/src/ssr/hydrate.ts +82 -0
- package/src/ssr/index.ts +70 -0
- package/src/ssr/render.ts +508 -0
- package/src/ssr/serialize.ts +296 -0
- package/src/ssr/types.ts +81 -0
- package/src/store/create-store.ts +467 -329
- package/src/store/define-store.ts +2 -1
- package/src/store/index.ts +27 -22
- package/src/store/mapping.ts +2 -1
- package/src/store/persisted.ts +249 -61
- package/src/store/types.ts +247 -94
- package/src/store/utils.ts +135 -141
- package/src/store/watch.ts +2 -1
- package/src/storybook/index.ts +480 -0
- package/src/testing/index.ts +42 -0
- package/src/testing/testing.ts +593 -0
- package/src/testing/types.ts +170 -0
- package/src/view/custom-directives.ts +30 -0
- package/src/view/evaluate.ts +292 -290
- package/src/view/process.ts +108 -92
- package/dist/component-CY5MVoYN.js +0 -531
- package/dist/component-CY5MVoYN.js.map +0 -1
- package/dist/config-DRmZZno3.js.map +0 -1
- package/dist/core-CK2Mfpf4.js +0 -648
- package/dist/core-CK2Mfpf4.js.map +0 -1
- package/dist/motion-C5DRdPnO.js +0 -415
- package/dist/motion-C5DRdPnO.js.map +0 -1
- package/dist/platform-B7JhGBc7.js.map +0 -1
- package/dist/reactive-BDya-ia8.js +0 -253
- package/dist/reactive-BDya-ia8.js.map +0 -1
- package/dist/router-CijiICxt.js +0 -188
- package/dist/router-CijiICxt.js.map +0 -1
- package/dist/sanitize-jyJ2ryE2.js.map +0 -1
- package/dist/store-CPK9E62U.js +0 -262
- package/dist/store-CPK9E62U.js.map +0 -1
- package/dist/view-Cdi0g-qo.js +0 -396
- package/dist/view-Cdi0g-qo.js.map +0 -1
|
@@ -4,9 +4,58 @@
|
|
|
4
4
|
* @module bquery/component
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import type { CleanupFn } from '../reactive/signal';
|
|
8
|
+
import { effect, untrack } from '../reactive/signal';
|
|
7
9
|
import { sanitizeHtml } from '../security/sanitize';
|
|
8
10
|
import { coercePropValue } from './props';
|
|
9
|
-
import
|
|
11
|
+
import { createComponentScope, setCurrentScope, type ComponentScope } from './scope';
|
|
12
|
+
import type {
|
|
13
|
+
AttributeChange,
|
|
14
|
+
ComponentClass,
|
|
15
|
+
ComponentDefinition,
|
|
16
|
+
ComponentSignalLike,
|
|
17
|
+
ComponentSignals,
|
|
18
|
+
ComponentStateShape,
|
|
19
|
+
PropDefinition,
|
|
20
|
+
ShadowMode,
|
|
21
|
+
} from './types';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Base extra tags preserved for component shadow DOM renders in addition to the
|
|
25
|
+
* global sanitizer defaults. `slot` must remain allowed here because shadow DOM
|
|
26
|
+
* content projection depends on authored `<slot>` elements in component render
|
|
27
|
+
* output.
|
|
28
|
+
*/
|
|
29
|
+
const COMPONENT_ALLOWED_TAGS = ['slot'];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Base extra attributes preserved for component shadow DOM renders in addition
|
|
33
|
+
* to the global sanitizer defaults.
|
|
34
|
+
*/
|
|
35
|
+
const COMPONENT_ALLOWED_ATTRIBUTES = [
|
|
36
|
+
'part',
|
|
37
|
+
// Standard form attributes required by interactive shadow DOM content
|
|
38
|
+
'disabled',
|
|
39
|
+
'checked',
|
|
40
|
+
'placeholder',
|
|
41
|
+
'value',
|
|
42
|
+
'rows',
|
|
43
|
+
'cols',
|
|
44
|
+
'readonly',
|
|
45
|
+
'required',
|
|
46
|
+
'maxlength',
|
|
47
|
+
'minlength',
|
|
48
|
+
'max',
|
|
49
|
+
'min',
|
|
50
|
+
'step',
|
|
51
|
+
'pattern',
|
|
52
|
+
'autocomplete',
|
|
53
|
+
'autofocus',
|
|
54
|
+
'for',
|
|
55
|
+
'multiple',
|
|
56
|
+
'selected',
|
|
57
|
+
'wrap',
|
|
58
|
+
];
|
|
10
59
|
|
|
11
60
|
/**
|
|
12
61
|
* Creates a custom element class for a component definition.
|
|
@@ -18,23 +67,66 @@ import type { ComponentDefinition, PropDefinition } from './types';
|
|
|
18
67
|
* @param tagName - The custom element tag name (used for diagnostics)
|
|
19
68
|
* @param definition - The component configuration
|
|
20
69
|
*/
|
|
21
|
-
|
|
70
|
+
const createComponentClass = <
|
|
71
|
+
TProps extends Record<string, unknown>,
|
|
72
|
+
TState extends Record<string, unknown> | undefined = undefined,
|
|
73
|
+
TSignals extends ComponentSignals = Record<string, never>,
|
|
74
|
+
>(
|
|
22
75
|
tagName: string,
|
|
23
|
-
definition: ComponentDefinition<TProps>
|
|
24
|
-
):
|
|
76
|
+
definition: ComponentDefinition<TProps, TState, TSignals>
|
|
77
|
+
): ComponentClass<TState> => {
|
|
78
|
+
const componentAllowedTags = [
|
|
79
|
+
...COMPONENT_ALLOWED_TAGS,
|
|
80
|
+
...(definition.sanitize?.allowTags ?? []),
|
|
81
|
+
];
|
|
82
|
+
const componentAllowedAttributes = [
|
|
83
|
+
...COMPONENT_ALLOWED_ATTRIBUTES,
|
|
84
|
+
...(definition.sanitize?.allowAttributes ?? []),
|
|
85
|
+
];
|
|
86
|
+
const signalSources = Object.values(definition.signals ?? {}) as ComponentSignalLike<unknown>[];
|
|
87
|
+
|
|
88
|
+
/** Resolve the Shadow DOM mode from the `shadow` option. */
|
|
89
|
+
const resolveShadowMode = (option: ShadowMode | undefined): 'open' | 'closed' | false => {
|
|
90
|
+
if (option === false) return false;
|
|
91
|
+
if (option === 'closed') return 'closed';
|
|
92
|
+
// true, 'open', or undefined all resolve to 'open'
|
|
93
|
+
return 'open';
|
|
94
|
+
};
|
|
95
|
+
const shadowMode = resolveShadowMode(definition.shadow);
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Merges prop-derived observed attributes with any extra attributes from
|
|
99
|
+
* `observeAttributes`, deduplicating to avoid redundant callbacks.
|
|
100
|
+
*/
|
|
101
|
+
const observedAttrs = Array.from(
|
|
102
|
+
new Set([...Object.keys(definition.props ?? {}), ...(definition.observeAttributes ?? [])])
|
|
103
|
+
);
|
|
104
|
+
|
|
25
105
|
class BQueryComponent extends HTMLElement {
|
|
26
106
|
/** Internal state object for the component */
|
|
27
|
-
private readonly state = {
|
|
107
|
+
private readonly state: ComponentStateShape<TState> = {
|
|
108
|
+
...(definition.state ?? {}),
|
|
109
|
+
} as ComponentStateShape<TState>;
|
|
28
110
|
/** Typed props object populated from attributes */
|
|
29
111
|
private props = {} as TProps;
|
|
30
112
|
/** Tracks missing required props for validation during connectedCallback */
|
|
31
113
|
private missingRequiredProps = new Set<string>();
|
|
32
114
|
/** Tracks whether the component has completed its initial mount */
|
|
33
115
|
private hasMounted = false;
|
|
116
|
+
/** Cleanup for external signal subscriptions */
|
|
117
|
+
private signalEffectCleanup?: CleanupFn;
|
|
118
|
+
/** Component-scoped reactive resource tracker */
|
|
119
|
+
private scope?: ComponentScope;
|
|
120
|
+
/** Render target for open/closed shadow roots or the host element when shadow DOM is disabled */
|
|
121
|
+
private readonly renderRootNode: HTMLElement | ShadowRoot;
|
|
34
122
|
|
|
35
123
|
constructor() {
|
|
36
124
|
super();
|
|
37
|
-
|
|
125
|
+
if (shadowMode !== false) {
|
|
126
|
+
this.renderRootNode = this.attachShadow({ mode: shadowMode });
|
|
127
|
+
} else {
|
|
128
|
+
this.renderRootNode = this;
|
|
129
|
+
}
|
|
38
130
|
this.syncProps();
|
|
39
131
|
}
|
|
40
132
|
|
|
@@ -42,7 +134,7 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
42
134
|
* Returns the list of attributes to observe for changes.
|
|
43
135
|
*/
|
|
44
136
|
static get observedAttributes(): string[] {
|
|
45
|
-
return
|
|
137
|
+
return observedAttrs;
|
|
46
138
|
}
|
|
47
139
|
|
|
48
140
|
/**
|
|
@@ -50,13 +142,28 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
50
142
|
*/
|
|
51
143
|
connectedCallback(): void {
|
|
52
144
|
try {
|
|
53
|
-
// Defer initial
|
|
54
|
-
//
|
|
55
|
-
|
|
145
|
+
// Defer only the initial mount until all required props are present.
|
|
146
|
+
// Already-mounted components must still reconnect their signal
|
|
147
|
+
// subscriptions so reactive updates can resume after reattachment.
|
|
148
|
+
if (!this.hasMounted && this.missingRequiredProps.size > 0) {
|
|
56
149
|
// Component will mount once all required props are satisfied
|
|
57
150
|
// via attributeChangedCallback
|
|
58
151
|
return;
|
|
59
152
|
}
|
|
153
|
+
if (this.hasMounted) {
|
|
154
|
+
// Recreate scope for reconnected component
|
|
155
|
+
this.scope = createComponentScope();
|
|
156
|
+
const previousScope = setCurrentScope(this.scope);
|
|
157
|
+
try {
|
|
158
|
+
definition.connected?.call(this);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
this.handleError(error as Error);
|
|
161
|
+
} finally {
|
|
162
|
+
setCurrentScope(previousScope);
|
|
163
|
+
}
|
|
164
|
+
this.setupSignalSubscriptions(true);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
60
167
|
this.mount();
|
|
61
168
|
} catch (error) {
|
|
62
169
|
this.handleError(error as Error);
|
|
@@ -70,9 +177,24 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
70
177
|
*/
|
|
71
178
|
private mount(): void {
|
|
72
179
|
if (this.hasMounted) return;
|
|
73
|
-
|
|
74
|
-
|
|
180
|
+
const previousScope = setCurrentScope(this.ensureScope());
|
|
181
|
+
let hookError = false;
|
|
182
|
+
try {
|
|
183
|
+
definition.beforeMount?.call(this);
|
|
184
|
+
definition.connected?.call(this);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
hookError = true;
|
|
187
|
+
this.handleError(error as Error);
|
|
188
|
+
} finally {
|
|
189
|
+
setCurrentScope(previousScope);
|
|
190
|
+
}
|
|
191
|
+
if (hookError) {
|
|
192
|
+
this.scope?.dispose();
|
|
193
|
+
this.scope = undefined;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
75
196
|
this.render();
|
|
197
|
+
this.setupSignalSubscriptions();
|
|
76
198
|
this.hasMounted = true;
|
|
77
199
|
}
|
|
78
200
|
|
|
@@ -81,6 +203,11 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
81
203
|
*/
|
|
82
204
|
disconnectedCallback(): void {
|
|
83
205
|
try {
|
|
206
|
+
this.signalEffectCleanup?.();
|
|
207
|
+
this.signalEffectCleanup = undefined;
|
|
208
|
+
// Dispose all scoped reactive resources (useSignal, useComputed, useEffect)
|
|
209
|
+
this.scope?.dispose();
|
|
210
|
+
this.scope = undefined;
|
|
84
211
|
definition.disconnected?.call(this);
|
|
85
212
|
} catch (error) {
|
|
86
213
|
this.handleError(error as Error);
|
|
@@ -90,17 +217,24 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
90
217
|
/**
|
|
91
218
|
* Called when an observed attribute changes.
|
|
92
219
|
*/
|
|
93
|
-
attributeChangedCallback(
|
|
94
|
-
_name: string,
|
|
95
|
-
_oldValue: string | null,
|
|
96
|
-
_newValue: string | null
|
|
97
|
-
): void {
|
|
220
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {
|
|
98
221
|
try {
|
|
222
|
+
const previousProps = this.cloneProps();
|
|
99
223
|
this.syncProps();
|
|
100
224
|
|
|
225
|
+
// Fire the user-facing onAttributeChanged hook for every observed attribute change
|
|
226
|
+
if (definition.onAttributeChanged) {
|
|
227
|
+
const previousScope = setCurrentScope(this.ensureScope());
|
|
228
|
+
try {
|
|
229
|
+
definition.onAttributeChanged.call(this, name, oldValue, newValue);
|
|
230
|
+
} finally {
|
|
231
|
+
setCurrentScope(previousScope);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
101
235
|
if (this.hasMounted) {
|
|
102
236
|
// Component already mounted - trigger update render
|
|
103
|
-
this.render(true);
|
|
237
|
+
this.render(true, previousProps, { name, oldValue, newValue });
|
|
104
238
|
} else if (this.isConnected && this.missingRequiredProps.size === 0) {
|
|
105
239
|
// All required props are now satisfied and element is connected
|
|
106
240
|
// Trigger the deferred initial mount
|
|
@@ -111,6 +245,24 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
111
245
|
}
|
|
112
246
|
}
|
|
113
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Called when the element is moved to a new document (e.g. via `document.adoptNode`).
|
|
250
|
+
*/
|
|
251
|
+
adoptedCallback(): void {
|
|
252
|
+
if (!definition.onAdopted) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const previousScope = setCurrentScope(this.ensureScope());
|
|
257
|
+
try {
|
|
258
|
+
definition.onAdopted.call(this);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
this.handleError(error as Error);
|
|
261
|
+
} finally {
|
|
262
|
+
setCurrentScope(previousScope);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
114
266
|
/**
|
|
115
267
|
* Handles errors during component lifecycle.
|
|
116
268
|
* @internal
|
|
@@ -123,15 +275,26 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
123
275
|
}
|
|
124
276
|
}
|
|
125
277
|
|
|
278
|
+
/**
|
|
279
|
+
* Ensures the component has an active scope for scoped reactive primitives.
|
|
280
|
+
* @internal
|
|
281
|
+
*/
|
|
282
|
+
private ensureScope(): ComponentScope {
|
|
283
|
+
return (this.scope ??= createComponentScope());
|
|
284
|
+
}
|
|
285
|
+
|
|
126
286
|
/**
|
|
127
287
|
* Updates a state property and triggers a re-render.
|
|
128
288
|
*
|
|
129
289
|
* @param key - The state property key
|
|
130
290
|
* @param value - The new value
|
|
131
291
|
*/
|
|
132
|
-
setState
|
|
292
|
+
setState<TKey extends keyof ComponentStateShape<TState>>(
|
|
293
|
+
key: TKey,
|
|
294
|
+
value: ComponentStateShape<TState>[TKey]
|
|
295
|
+
): void {
|
|
133
296
|
this.state[key] = value;
|
|
134
|
-
this.render(true);
|
|
297
|
+
this.render(true, this.cloneProps(), undefined, false);
|
|
135
298
|
}
|
|
136
299
|
|
|
137
300
|
/**
|
|
@@ -140,8 +303,58 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
140
303
|
* @param key - The state property key
|
|
141
304
|
* @returns The current value
|
|
142
305
|
*/
|
|
143
|
-
getState<
|
|
144
|
-
|
|
306
|
+
getState<TKey extends keyof ComponentStateShape<TState>>(
|
|
307
|
+
key: TKey
|
|
308
|
+
): ComponentStateShape<TState>[TKey];
|
|
309
|
+
getState<TResult = unknown>(key: string): TResult;
|
|
310
|
+
getState(key: string): unknown {
|
|
311
|
+
return (this.state as Record<string, unknown>)[key];
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Subscribes to declared reactive sources and re-renders on change.
|
|
316
|
+
*
|
|
317
|
+
* @param renderOnInitialRun - When true, immediately re-renders after
|
|
318
|
+
* re-subscribing so detached components resync with any signal changes
|
|
319
|
+
* that happened while they were disconnected.
|
|
320
|
+
* @internal
|
|
321
|
+
*/
|
|
322
|
+
private setupSignalSubscriptions(renderOnInitialRun = false): void {
|
|
323
|
+
if (this.signalEffectCleanup || signalSources.length === 0) return;
|
|
324
|
+
|
|
325
|
+
let isInitialRun = true;
|
|
326
|
+
this.signalEffectCleanup = effect(() => {
|
|
327
|
+
try {
|
|
328
|
+
for (const source of signalSources) {
|
|
329
|
+
// Intentionally read each source to register this effect as a subscriber.
|
|
330
|
+
void source.value;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (isInitialRun) {
|
|
334
|
+
isInitialRun = false;
|
|
335
|
+
if (renderOnInitialRun && this.hasMounted && this.isConnected) {
|
|
336
|
+
// Signal-driven reconnect renders do not change props, so the
|
|
337
|
+
// previous-props snapshot is the current prop set at reconnect time.
|
|
338
|
+
const previousProps = this.cloneProps();
|
|
339
|
+
untrack(() => {
|
|
340
|
+
this.render(true, previousProps, undefined, false);
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (!this.hasMounted || !this.isConnected) return;
|
|
347
|
+
|
|
348
|
+
// Signal updates leave props unchanged, so cloning the current props
|
|
349
|
+
// provides the previous-props snapshot expected by beforeUpdate().
|
|
350
|
+
const previousProps = this.cloneProps();
|
|
351
|
+
untrack(() => {
|
|
352
|
+
this.render(true, previousProps, undefined, false);
|
|
353
|
+
});
|
|
354
|
+
} catch (error) {
|
|
355
|
+
this.handleError(error as Error);
|
|
356
|
+
}
|
|
357
|
+
});
|
|
145
358
|
}
|
|
146
359
|
|
|
147
360
|
/**
|
|
@@ -184,13 +397,40 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
184
397
|
}
|
|
185
398
|
|
|
186
399
|
/**
|
|
187
|
-
*
|
|
400
|
+
* Creates a shallow snapshot of the current props for lifecycle diffing.
|
|
401
|
+
* A shallow copy is sufficient because component props are re-derived from
|
|
402
|
+
* reflected attributes on each update, so nested object mutation is not
|
|
403
|
+
* tracked as part of this lifecycle diff.
|
|
404
|
+
* @internal
|
|
405
|
+
*/
|
|
406
|
+
private cloneProps(): TProps {
|
|
407
|
+
return { ...(this.props as Record<string, unknown>) } as TProps;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Renders the component to its shadow root or host element.
|
|
188
412
|
* @internal
|
|
189
413
|
*/
|
|
190
|
-
private render(
|
|
414
|
+
private render(): void;
|
|
415
|
+
private render(triggerUpdated: true, oldProps: TProps, change?: AttributeChange): void;
|
|
416
|
+
private render(
|
|
417
|
+
triggerUpdated: true,
|
|
418
|
+
oldProps: TProps,
|
|
419
|
+
change: AttributeChange | undefined,
|
|
420
|
+
runBeforeUpdate: boolean
|
|
421
|
+
): void;
|
|
422
|
+
private render(
|
|
423
|
+
triggerUpdated = false,
|
|
424
|
+
oldProps?: TProps,
|
|
425
|
+
change?: AttributeChange,
|
|
426
|
+
runBeforeUpdate = true
|
|
427
|
+
): void {
|
|
191
428
|
try {
|
|
192
|
-
if (triggerUpdated && definition.beforeUpdate) {
|
|
193
|
-
|
|
429
|
+
if (triggerUpdated && runBeforeUpdate && definition.beforeUpdate) {
|
|
430
|
+
if (!oldProps) {
|
|
431
|
+
throw new Error('bQuery component: previous props are required for update renders');
|
|
432
|
+
}
|
|
433
|
+
const shouldUpdate = definition.beforeUpdate.call(this, this.props, oldProps);
|
|
194
434
|
if (shouldUpdate === false) return;
|
|
195
435
|
}
|
|
196
436
|
|
|
@@ -198,11 +438,12 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
198
438
|
this.dispatchEvent(new CustomEvent(event, { detail, bubbles: true, composed: true }));
|
|
199
439
|
};
|
|
200
440
|
|
|
201
|
-
|
|
441
|
+
const renderRoot = this.renderRootNode;
|
|
202
442
|
|
|
203
443
|
const markup = definition.render({
|
|
204
444
|
props: this.props,
|
|
205
445
|
state: this.state,
|
|
446
|
+
signals: (definition.signals ?? {}) as TSignals,
|
|
206
447
|
emit,
|
|
207
448
|
});
|
|
208
449
|
|
|
@@ -211,42 +452,29 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
211
452
|
// the stylistic `part` attribute, and standard form/input attributes without
|
|
212
453
|
// relaxing the global DOM sanitization rules.
|
|
213
454
|
const sanitizedMarkup = sanitizeHtml(markup, {
|
|
214
|
-
allowTags:
|
|
215
|
-
allowAttributes:
|
|
216
|
-
'part',
|
|
217
|
-
// Standard form attributes required by interactive shadow DOM content
|
|
218
|
-
'disabled',
|
|
219
|
-
'checked',
|
|
220
|
-
'placeholder',
|
|
221
|
-
'value',
|
|
222
|
-
'rows',
|
|
223
|
-
'cols',
|
|
224
|
-
'readonly',
|
|
225
|
-
'required',
|
|
226
|
-
'maxlength',
|
|
227
|
-
'minlength',
|
|
228
|
-
'max',
|
|
229
|
-
'min',
|
|
230
|
-
'step',
|
|
231
|
-
'pattern',
|
|
232
|
-
'autocomplete',
|
|
233
|
-
'autofocus',
|
|
234
|
-
'for',
|
|
235
|
-
'multiple',
|
|
236
|
-
'selected',
|
|
237
|
-
'wrap',
|
|
238
|
-
],
|
|
455
|
+
allowTags: componentAllowedTags,
|
|
456
|
+
allowAttributes: componentAllowedAttributes,
|
|
239
457
|
});
|
|
240
|
-
|
|
458
|
+
let existingStyleElement: HTMLStyleElement | null = null;
|
|
459
|
+
if (definition.styles) {
|
|
460
|
+
existingStyleElement = renderRoot.querySelector<HTMLStyleElement>(
|
|
461
|
+
'style[data-bquery-component-style]'
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
renderRoot.innerHTML = sanitizedMarkup;
|
|
241
466
|
|
|
242
467
|
if (definition.styles) {
|
|
243
|
-
const styleElement = document.createElement('style');
|
|
468
|
+
const styleElement = existingStyleElement ?? document.createElement('style');
|
|
469
|
+
if (!existingStyleElement) {
|
|
470
|
+
styleElement.setAttribute('data-bquery-component-style', '');
|
|
471
|
+
}
|
|
244
472
|
styleElement.textContent = definition.styles;
|
|
245
|
-
|
|
473
|
+
renderRoot.prepend(styleElement);
|
|
246
474
|
}
|
|
247
475
|
|
|
248
476
|
if (triggerUpdated) {
|
|
249
|
-
definition.updated?.call(this);
|
|
477
|
+
definition.updated?.call(this, change);
|
|
250
478
|
}
|
|
251
479
|
} catch (error) {
|
|
252
480
|
this.handleError(error as Error);
|
|
@@ -254,9 +482,48 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
254
482
|
}
|
|
255
483
|
}
|
|
256
484
|
|
|
257
|
-
return BQueryComponent
|
|
485
|
+
return BQueryComponent as ComponentClass<TState>;
|
|
258
486
|
};
|
|
259
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Creates a custom element class for a component definition.
|
|
490
|
+
*
|
|
491
|
+
* This is useful when you want to extend or register the class manually
|
|
492
|
+
* (e.g. with different tag names in tests or custom registries).
|
|
493
|
+
*
|
|
494
|
+
* @template TProps - Type of the component's props
|
|
495
|
+
* @template TState - Type of the component's internal state. When provided,
|
|
496
|
+
* `definition.state` is required, `render({ state })` is strongly typed, and
|
|
497
|
+
* returned instances expose typed `getState()` / `setState()` helpers.
|
|
498
|
+
* @param tagName - The custom element tag name (used for diagnostics)
|
|
499
|
+
* @param definition - The component configuration
|
|
500
|
+
*/
|
|
501
|
+
export function defineComponent<
|
|
502
|
+
TProps extends Record<string, unknown>,
|
|
503
|
+
TSignals extends ComponentSignals = Record<string, never>,
|
|
504
|
+
>(
|
|
505
|
+
tagName: string,
|
|
506
|
+
definition: ComponentDefinition<TProps, undefined, TSignals>
|
|
507
|
+
): ComponentClass<undefined>;
|
|
508
|
+
export function defineComponent<
|
|
509
|
+
TProps extends Record<string, unknown>,
|
|
510
|
+
TState extends Record<string, unknown>,
|
|
511
|
+
TSignals extends ComponentSignals = Record<string, never>,
|
|
512
|
+
>(
|
|
513
|
+
tagName: string,
|
|
514
|
+
definition: ComponentDefinition<TProps, TState, TSignals>
|
|
515
|
+
): ComponentClass<TState>;
|
|
516
|
+
export function defineComponent<
|
|
517
|
+
TProps extends Record<string, unknown>,
|
|
518
|
+
TState extends Record<string, unknown> | undefined = undefined,
|
|
519
|
+
TSignals extends ComponentSignals = Record<string, never>,
|
|
520
|
+
>(
|
|
521
|
+
tagName: string,
|
|
522
|
+
definition: ComponentDefinition<TProps, TState, TSignals>
|
|
523
|
+
): ComponentClass<TState> {
|
|
524
|
+
return createComponentClass(tagName, definition);
|
|
525
|
+
}
|
|
526
|
+
|
|
260
527
|
/**
|
|
261
528
|
* Defines and registers a custom Web Component.
|
|
262
529
|
*
|
|
@@ -265,12 +532,15 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
265
532
|
* and automatically re-renders when observed attributes change.
|
|
266
533
|
*
|
|
267
534
|
* @template TProps - Type of the component's props
|
|
535
|
+
* @template TState - Type of the component's internal state. When provided,
|
|
536
|
+
* `definition.state` is required and lifecycle hooks receive typed state
|
|
537
|
+
* helpers via `this.getState()` / `this.setState()`.
|
|
268
538
|
* @param tagName - The custom element tag name (must contain a hyphen)
|
|
269
539
|
* @param definition - The component configuration
|
|
270
540
|
*
|
|
271
541
|
* @example
|
|
272
542
|
* ```ts
|
|
273
|
-
* component('counter-button', {
|
|
543
|
+
* component<{ start: number }, { count: number }>('counter-button', {
|
|
274
544
|
* props: {
|
|
275
545
|
* start: { type: Number, default: 0 },
|
|
276
546
|
* },
|
|
@@ -283,7 +553,7 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
283
553
|
* const handleClick = (event: Event) => {
|
|
284
554
|
* const target = event.target as HTMLElement | null;
|
|
285
555
|
* if (target?.matches('button')) {
|
|
286
|
-
* this.setState('count',
|
|
556
|
+
* this.setState('count', this.getState('count') + 1);
|
|
287
557
|
* }
|
|
288
558
|
* };
|
|
289
559
|
* this.shadowRoot?.addEventListener('click', handleClick);
|
|
@@ -307,13 +577,23 @@ export const defineComponent = <TProps extends Record<string, unknown>>(
|
|
|
307
577
|
* });
|
|
308
578
|
* ```
|
|
309
579
|
*/
|
|
310
|
-
export
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
): void
|
|
314
|
-
|
|
580
|
+
export function component<
|
|
581
|
+
TProps extends Record<string, unknown>,
|
|
582
|
+
TSignals extends ComponentSignals = Record<string, never>,
|
|
583
|
+
>(tagName: string, definition: ComponentDefinition<TProps, undefined, TSignals>): void;
|
|
584
|
+
export function component<
|
|
585
|
+
TProps extends Record<string, unknown>,
|
|
586
|
+
TState extends Record<string, unknown>,
|
|
587
|
+
TSignals extends ComponentSignals = Record<string, never>,
|
|
588
|
+
>(tagName: string, definition: ComponentDefinition<TProps, TState, TSignals>): void;
|
|
589
|
+
export function component<
|
|
590
|
+
TProps extends Record<string, unknown>,
|
|
591
|
+
TState extends Record<string, unknown> | undefined = undefined,
|
|
592
|
+
TSignals extends ComponentSignals = Record<string, never>,
|
|
593
|
+
>(tagName: string, definition: ComponentDefinition<TProps, TState, TSignals>): void {
|
|
594
|
+
const elementClass = createComponentClass(tagName, definition);
|
|
315
595
|
|
|
316
596
|
if (!customElements.get(tagName)) {
|
|
317
597
|
customElements.define(tagName, elementClass);
|
|
318
598
|
}
|
|
319
|
-
}
|
|
599
|
+
}
|