@pwfabric/runtime 0.0.0-stage → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +90 -0
- package/README.md +43 -2
- package/dist/a11y/announcer.d.ts +65 -0
- package/dist/a11y/announcer.js +140 -0
- package/dist/a11y/announcer.js.map +1 -0
- package/dist/a11y/contrast.d.ts +54 -0
- package/dist/a11y/contrast.js +93 -0
- package/dist/a11y/contrast.js.map +1 -0
- package/dist/a11y/focus.d.ts +123 -0
- package/dist/a11y/focus.js +282 -0
- package/dist/a11y/focus.js.map +1 -0
- package/dist/a11y/index.d.ts +21 -0
- package/dist/a11y/index.js +18 -0
- package/dist/a11y/index.js.map +1 -0
- package/dist/a11y/keyboard.d.ts +144 -0
- package/dist/a11y/keyboard.js +317 -0
- package/dist/a11y/keyboard.js.map +1 -0
- package/dist/adapters/default-image.d.ts +25 -0
- package/dist/adapters/default-image.js +37 -0
- package/dist/adapters/default-image.js.map +1 -0
- package/dist/adapters/index.d.ts +27 -0
- package/dist/adapters/index.js +28 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/next-image.d.ts +38 -0
- package/dist/adapters/next-image.js +124 -0
- package/dist/adapters/next-image.js.map +1 -0
- package/dist/adapters/types.d.ts +61 -0
- package/dist/adapters/types.js +11 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/analytics/index.d.ts +14 -0
- package/dist/analytics/index.js +15 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/tracker.d.ts +65 -0
- package/dist/analytics/tracker.js +251 -0
- package/dist/analytics/tracker.js.map +1 -0
- package/dist/analytics/types.d.ts +130 -0
- package/dist/analytics/types.js +11 -0
- package/dist/analytics/types.js.map +1 -0
- package/dist/auth/index.d.ts +15 -0
- package/dist/auth/index.js +14 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/provider.d.ts +132 -0
- package/dist/auth/provider.js +473 -0
- package/dist/auth/provider.js.map +1 -0
- package/dist/auth/types.d.ts +117 -0
- package/dist/auth/types.js +9 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/binding/collection.d.ts +190 -0
- package/dist/binding/collection.js +358 -0
- package/dist/binding/collection.js.map +1 -0
- package/dist/binding/datasource.d.ts +319 -0
- package/dist/binding/datasource.js +556 -0
- package/dist/binding/datasource.js.map +1 -0
- package/dist/binding/engine.d.ts +65 -0
- package/dist/binding/engine.js +268 -0
- package/dist/binding/engine.js.map +1 -0
- package/dist/binding/expression.d.ts +150 -0
- package/dist/binding/expression.js +787 -0
- package/dist/binding/expression.js.map +1 -0
- package/dist/binding/index.d.ts +19 -0
- package/dist/binding/index.js +14 -0
- package/dist/binding/index.js.map +1 -0
- package/dist/binding/two-way.d.ts +149 -0
- package/dist/binding/two-way.js +462 -0
- package/dist/binding/two-way.js.map +1 -0
- package/dist/binding/types.d.ts +119 -0
- package/dist/binding/types.js +9 -0
- package/dist/binding/types.js.map +1 -0
- package/dist/blocks/component-types.d.ts +81 -0
- package/dist/blocks/component-types.js +11 -0
- package/dist/blocks/component-types.js.map +1 -0
- package/dist/blocks/composition-rules.d.ts +168 -0
- package/dist/blocks/composition-rules.js +391 -0
- package/dist/blocks/composition-rules.js.map +1 -0
- package/dist/blocks/hooks.d.ts +31 -0
- package/dist/blocks/hooks.js +42 -0
- package/dist/blocks/hooks.js.map +1 -0
- package/dist/blocks/index.d.ts +14 -0
- package/dist/blocks/index.js +23 -0
- package/dist/blocks/index.js.map +1 -0
- package/dist/blocks/registry.d.ts +84 -0
- package/dist/blocks/registry.js +136 -0
- package/dist/blocks/registry.js.map +1 -0
- package/dist/blocks/rule-engine.d.ts +131 -0
- package/dist/blocks/rule-engine.js +321 -0
- package/dist/blocks/rule-engine.js.map +1 -0
- package/dist/blocks/surface-event-context.d.ts +13 -0
- package/dist/blocks/surface-event-context.js +14 -0
- package/dist/blocks/surface-event-context.js.map +1 -0
- package/dist/blocks/surface-id-context.d.ts +13 -0
- package/dist/blocks/surface-id-context.js +15 -0
- package/dist/blocks/surface-id-context.js.map +1 -0
- package/dist/bus.d.ts +41 -0
- package/dist/bus.js +158 -0
- package/dist/bus.js.map +1 -0
- package/dist/cache/index.d.ts +9 -0
- package/dist/cache/index.js +10 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/memory.d.ts +32 -0
- package/dist/cache/memory.js +138 -0
- package/dist/cache/memory.js.map +1 -0
- package/dist/cache/types.d.ts +62 -0
- package/dist/cache/types.js +9 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/capability/index.d.ts +72 -0
- package/dist/capability/index.js +87 -0
- package/dist/capability/index.js.map +1 -0
- package/dist/capability/kernel-capabilities.d.ts +31 -0
- package/dist/capability/kernel-capabilities.js +36 -0
- package/dist/capability/kernel-capabilities.js.map +1 -0
- package/dist/capability/platform-capabilities.d.ts +71 -0
- package/dist/capability/platform-capabilities.js +267 -0
- package/dist/capability/platform-capabilities.js.map +1 -0
- package/dist/capability/type-mapping.d.ts +70 -0
- package/dist/capability/type-mapping.js +107 -0
- package/dist/capability/type-mapping.js.map +1 -0
- package/dist/capability/validation.d.ts +46 -0
- package/dist/capability/validation.js +54 -0
- package/dist/capability/validation.js.map +1 -0
- package/dist/connectors/declared-connector.d.ts +48 -0
- package/dist/connectors/declared-connector.js +333 -0
- package/dist/connectors/declared-connector.js.map +1 -0
- package/dist/connectors/engine-registry.d.ts +50 -0
- package/dist/connectors/engine-registry.js +135 -0
- package/dist/connectors/engine-registry.js.map +1 -0
- package/dist/connectors/index.d.ts +14 -0
- package/dist/connectors/index.js +14 -0
- package/dist/connectors/index.js.map +1 -0
- package/dist/connectors/module-loader.d.ts +70 -0
- package/dist/connectors/module-loader.js +143 -0
- package/dist/connectors/module-loader.js.map +1 -0
- package/dist/connectors/types.d.ts +174 -0
- package/dist/connectors/types.js +23 -0
- package/dist/connectors/types.js.map +1 -0
- package/dist/context.d.ts +27 -0
- package/dist/context.js +38 -0
- package/dist/context.js.map +1 -0
- package/dist/data/DataCapabilityProvider.d.ts +39 -0
- package/dist/data/DataCapabilityProvider.js +58 -0
- package/dist/data/DataCapabilityProvider.js.map +1 -0
- package/dist/data/index.d.ts +17 -0
- package/dist/data/index.js +18 -0
- package/dist/data/index.js.map +1 -0
- package/dist/data/manager.d.ts +40 -0
- package/dist/data/manager.js +442 -0
- package/dist/data/manager.js.map +1 -0
- package/dist/data/types.d.ts +218 -0
- package/dist/data/types.js +2 -0
- package/dist/data/types.js.map +1 -0
- package/dist/entity/aggregate.d.ts +8 -0
- package/dist/entity/aggregate.js +24 -0
- package/dist/entity/aggregate.js.map +1 -0
- package/dist/entity/apply-query.d.ts +58 -0
- package/dist/entity/apply-query.js +264 -0
- package/dist/entity/apply-query.js.map +1 -0
- package/dist/entity/behavior.d.ts +94 -0
- package/dist/entity/behavior.js +78 -0
- package/dist/entity/behavior.js.map +1 -0
- package/dist/entity/connector.d.ts +141 -0
- package/dist/entity/connector.js +89 -0
- package/dist/entity/connector.js.map +1 -0
- package/dist/entity/connectors/index.d.ts +12 -0
- package/dist/entity/connectors/index.js +11 -0
- package/dist/entity/connectors/index.js.map +1 -0
- package/dist/entity/connectors/static.d.ts +51 -0
- package/dist/entity/connectors/static.js +245 -0
- package/dist/entity/connectors/static.js.map +1 -0
- package/dist/entity/entity-datasource.d.ts +50 -0
- package/dist/entity/entity-datasource.js +33 -0
- package/dist/entity/entity-datasource.js.map +1 -0
- package/dist/entity/facade.d.ts +70 -0
- package/dist/entity/facade.js +70 -0
- package/dist/entity/facade.js.map +1 -0
- package/dist/entity/http-connector.d.ts +123 -0
- package/dist/entity/http-connector.js +295 -0
- package/dist/entity/http-connector.js.map +1 -0
- package/dist/entity/index.d.ts +38 -0
- package/dist/entity/index.js +31 -0
- package/dist/entity/index.js.map +1 -0
- package/dist/entity/postgres-connector.d.ts +64 -0
- package/dist/entity/postgres-connector.js +239 -0
- package/dist/entity/postgres-connector.js.map +1 -0
- package/dist/entity/registry.d.ts +59 -0
- package/dist/entity/registry.js +90 -0
- package/dist/entity/registry.js.map +1 -0
- package/dist/entity/store.d.ts +66 -0
- package/dist/entity/store.js +349 -0
- package/dist/entity/store.js.map +1 -0
- package/dist/entity/types.d.ts +180 -0
- package/dist/entity/types.js +10 -0
- package/dist/entity/types.js.map +1 -0
- package/dist/execution-context.d.ts +88 -0
- package/dist/execution-context.js +146 -0
- package/dist/execution-context.js.map +1 -0
- package/dist/executor.d.ts +27 -0
- package/dist/executor.js +33 -0
- package/dist/executor.js.map +1 -0
- package/dist/forms/form-entity-bridge.d.ts +94 -0
- package/dist/forms/form-entity-bridge.js +96 -0
- package/dist/forms/form-entity-bridge.js.map +1 -0
- package/dist/forms/form-write-target.d.ts +34 -0
- package/dist/forms/form-write-target.js +81 -0
- package/dist/forms/form-write-target.js.map +1 -0
- package/dist/forms/index.d.ts +22 -0
- package/dist/forms/index.js +25 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/forms/named-control-values.d.ts +27 -0
- package/dist/forms/named-control-values.js +42 -0
- package/dist/forms/named-control-values.js.map +1 -0
- package/dist/forms/processor.d.ts +55 -0
- package/dist/forms/processor.js +154 -0
- package/dist/forms/processor.js.map +1 -0
- package/dist/forms/types.d.ts +174 -0
- package/dist/forms/types.js +33 -0
- package/dist/forms/types.js.map +1 -0
- package/dist/forms/validator.d.ts +61 -0
- package/dist/forms/validator.js +218 -0
- package/dist/forms/validator.js.map +1 -0
- package/dist/graph/index.d.ts +10 -0
- package/dist/graph/index.js +9 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/resolver.d.ts +66 -0
- package/dist/graph/resolver.js +243 -0
- package/dist/graph/resolver.js.map +1 -0
- package/dist/graph/types.d.ts +125 -0
- package/dist/graph/types.js +9 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/hooks/useInstalledAtoms.d.ts +96 -0
- package/dist/hooks/useInstalledAtoms.js +92 -0
- package/dist/hooks/useInstalledAtoms.js.map +1 -0
- package/dist/i18n/index.d.ts +15 -0
- package/dist/i18n/index.js +14 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/translator.d.ts +76 -0
- package/dist/i18n/translator.js +357 -0
- package/dist/i18n/translator.js.map +1 -0
- package/dist/i18n/types.d.ts +93 -0
- package/dist/i18n/types.js +9 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel.d.ts +47 -0
- package/dist/kernel.js +258 -0
- package/dist/kernel.js.map +1 -0
- package/dist/perf/budget.d.ts +92 -0
- package/dist/perf/budget.js +122 -0
- package/dist/perf/budget.js.map +1 -0
- package/dist/perf/index.d.ts +16 -0
- package/dist/perf/index.js +13 -0
- package/dist/perf/index.js.map +1 -0
- package/dist/perf/render-timer.d.ts +90 -0
- package/dist/perf/render-timer.js +136 -0
- package/dist/perf/render-timer.js.map +1 -0
- package/dist/perf/reporter.d.ts +126 -0
- package/dist/perf/reporter.js +241 -0
- package/dist/perf/reporter.js.map +1 -0
- package/dist/perf/web-vitals.d.ts +111 -0
- package/dist/perf/web-vitals.js +268 -0
- package/dist/perf/web-vitals.js.map +1 -0
- package/dist/registry.d.ts +63 -0
- package/dist/registry.js +126 -0
- package/dist/registry.js.map +1 -0
- package/dist/render/BehaviorSurfaceProvider.d.ts +65 -0
- package/dist/render/BehaviorSurfaceProvider.js +185 -0
- package/dist/render/BehaviorSurfaceProvider.js.map +1 -0
- package/dist/render/BlockErrorBoundary.d.ts +26 -0
- package/dist/render/BlockErrorBoundary.js +41 -0
- package/dist/render/BlockErrorBoundary.js.map +1 -0
- package/dist/render/DataBoundSurfaceRenderer.d.ts +78 -0
- package/dist/render/DataBoundSurfaceRenderer.js +998 -0
- package/dist/render/DataBoundSurfaceRenderer.js.map +1 -0
- package/dist/render/DynamicBlockWrapper.d.ts +23 -0
- package/dist/render/DynamicBlockWrapper.js +117 -0
- package/dist/render/DynamicBlockWrapper.js.map +1 -0
- package/dist/render/appearance-resolver.d.ts +50 -0
- package/dist/render/appearance-resolver.js +78 -0
- package/dist/render/appearance-resolver.js.map +1 -0
- package/dist/render/capability-gate.d.ts +69 -0
- package/dist/render/capability-gate.js +94 -0
- package/dist/render/capability-gate.js.map +1 -0
- package/dist/render/conditional-states-css.d.ts +41 -0
- package/dist/render/conditional-states-css.js +82 -0
- package/dist/render/conditional-states-css.js.map +1 -0
- package/dist/render/connections-context.d.ts +31 -0
- package/dist/render/connections-context.js +34 -0
- package/dist/render/connections-context.js.map +1 -0
- package/dist/render/dark-theme-css.d.ts +36 -0
- package/dist/render/dark-theme-css.js +67 -0
- package/dist/render/dark-theme-css.js.map +1 -0
- package/dist/render/data-binding-types.d.ts +191 -0
- package/dist/render/data-binding-types.js +11 -0
- package/dist/render/data-binding-types.js.map +1 -0
- package/dist/render/data-cache.d.ts +30 -0
- package/dist/render/data-cache.js +37 -0
- package/dist/render/data-cache.js.map +1 -0
- package/dist/render/derive-dark-theme.d.ts +17 -0
- package/dist/render/derive-dark-theme.js +18 -0
- package/dist/render/derive-dark-theme.js.map +1 -0
- package/dist/render/dynamic-artifact-context.d.ts +77 -0
- package/dist/render/dynamic-artifact-context.js +89 -0
- package/dist/render/dynamic-artifact-context.js.map +1 -0
- package/dist/render/dynamic-block-loader.d.ts +80 -0
- package/dist/render/dynamic-block-loader.js +197 -0
- package/dist/render/dynamic-block-loader.js.map +1 -0
- package/dist/render/endpoint.d.ts +18 -0
- package/dist/render/endpoint.js +109 -0
- package/dist/render/endpoint.js.map +1 -0
- package/dist/render/entity-facade-context.d.ts +34 -0
- package/dist/render/entity-facade-context.js +37 -0
- package/dist/render/entity-facade-context.js.map +1 -0
- package/dist/render/group-states-css.d.ts +41 -0
- package/dist/render/group-states-css.js +73 -0
- package/dist/render/group-states-css.js.map +1 -0
- package/dist/render/hooks/useSurfaceEvents.d.ts +8 -0
- package/dist/render/hooks/useSurfaceEvents.js +9 -0
- package/dist/render/hooks/useSurfaceEvents.js.map +1 -0
- package/dist/render/hooks/useSurfaceId.d.ts +8 -0
- package/dist/render/hooks/useSurfaceId.js +9 -0
- package/dist/render/hooks/useSurfaceId.js.map +1 -0
- package/dist/render/index.d.ts +48 -0
- package/dist/render/index.js +61 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/interaction-rule-engine.d.ts +12 -0
- package/dist/render/interaction-rule-engine.js +47 -0
- package/dist/render/interaction-rule-engine.js.map +1 -0
- package/dist/render/keyframes-css.d.ts +31 -0
- package/dist/render/keyframes-css.js +44 -0
- package/dist/render/keyframes-css.js.map +1 -0
- package/dist/render/query-state.d.ts +3 -0
- package/dist/render/query-state.js +70 -0
- package/dist/render/query-state.js.map +1 -0
- package/dist/render/renderer.d.ts +44 -0
- package/dist/render/renderer.js +937 -0
- package/dist/render/renderer.js.map +1 -0
- package/dist/render/resolve-expressions.d.ts +37 -0
- package/dist/render/resolve-expressions.js +309 -0
- package/dist/render/resolve-expressions.js.map +1 -0
- package/dist/render/responsive-style-css.d.ts +42 -0
- package/dist/render/responsive-style-css.js +123 -0
- package/dist/render/responsive-style-css.js.map +1 -0
- package/dist/render/responsive.d.ts +49 -0
- package/dist/render/responsive.js +99 -0
- package/dist/render/responsive.js.map +1 -0
- package/dist/render/scoped-css.d.ts +71 -0
- package/dist/render/scoped-css.js +102 -0
- package/dist/render/scoped-css.js.map +1 -0
- package/dist/render/shell-selection.d.ts +69 -0
- package/dist/render/shell-selection.js +117 -0
- package/dist/render/shell-selection.js.map +1 -0
- package/dist/render/states-css.d.ts +32 -0
- package/dist/render/states-css.js +63 -0
- package/dist/render/states-css.js.map +1 -0
- package/dist/render/surface-data-context.d.ts +18 -0
- package/dist/render/surface-data-context.js +21 -0
- package/dist/render/surface-data-context.js.map +1 -0
- package/dist/render/surface-event-bus.d.ts +19 -0
- package/dist/render/surface-event-bus.js +68 -0
- package/dist/render/surface-event-bus.js.map +1 -0
- package/dist/render/surface-event-context.d.ts +11 -0
- package/dist/render/surface-event-context.js +12 -0
- package/dist/render/surface-event-context.js.map +1 -0
- package/dist/render/surface-id-context.d.ts +8 -0
- package/dist/render/surface-id-context.js +9 -0
- package/dist/render/surface-id-context.js.map +1 -0
- package/dist/render/theme-utils.d.ts +14 -0
- package/dist/render/theme-utils.js +15 -0
- package/dist/render/theme-utils.js.map +1 -0
- package/dist/render/types.d.ts +282 -0
- package/dist/render/types.js +9 -0
- package/dist/render/types.js.map +1 -0
- package/dist/render/visibility-css.d.ts +42 -0
- package/dist/render/visibility-css.js +119 -0
- package/dist/render/visibility-css.js.map +1 -0
- package/dist/render/width-scope.d.ts +34 -0
- package/dist/render/width-scope.js +44 -0
- package/dist/render/width-scope.js.map +1 -0
- package/dist/render/write-only-sources.d.ts +33 -0
- package/dist/render/write-only-sources.js +99 -0
- package/dist/render/write-only-sources.js.map +1 -0
- package/dist/routing/index.d.ts +14 -0
- package/dist/routing/index.js +15 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/router.d.ts +42 -0
- package/dist/routing/router.js +218 -0
- package/dist/routing/router.js.map +1 -0
- package/dist/routing/types.d.ts +124 -0
- package/dist/routing/types.js +9 -0
- package/dist/routing/types.js.map +1 -0
- package/dist/seo/generator.d.ts +39 -0
- package/dist/seo/generator.js +236 -0
- package/dist/seo/generator.js.map +1 -0
- package/dist/seo/index.d.ts +14 -0
- package/dist/seo/index.js +15 -0
- package/dist/seo/index.js.map +1 -0
- package/dist/seo/types.d.ts +181 -0
- package/dist/seo/types.js +9 -0
- package/dist/seo/types.js.map +1 -0
- package/dist/state/index.d.ts +15 -0
- package/dist/state/index.js +16 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/manager.d.ts +33 -0
- package/dist/state/manager.js +81 -0
- package/dist/state/manager.js.map +1 -0
- package/dist/state/store.d.ts +40 -0
- package/dist/state/store.js +145 -0
- package/dist/state/store.js.map +1 -0
- package/dist/state/types.d.ts +107 -0
- package/dist/state/types.js +9 -0
- package/dist/state/types.js.map +1 -0
- package/dist/surface/expression.d.ts +65 -0
- package/dist/surface/expression.js +179 -0
- package/dist/surface/expression.js.map +1 -0
- package/dist/surface/index.d.ts +32 -0
- package/dist/surface/index.js +25 -0
- package/dist/surface/index.js.map +1 -0
- package/dist/surface/interpreter.d.ts +96 -0
- package/dist/surface/interpreter.js +231 -0
- package/dist/surface/interpreter.js.map +1 -0
- package/dist/surface/layout.d.ts +54 -0
- package/dist/surface/layout.js +288 -0
- package/dist/surface/layout.js.map +1 -0
- package/dist/surface/output.d.ts +90 -0
- package/dist/surface/output.js +104 -0
- package/dist/surface/output.js.map +1 -0
- package/dist/surface/primitives.d.ts +180 -0
- package/dist/surface/primitives.js +339 -0
- package/dist/surface/primitives.js.map +1 -0
- package/dist/surface/renderer.d.ts +96 -0
- package/dist/surface/renderer.js +190 -0
- package/dist/surface/renderer.js.map +1 -0
- package/dist/surface/schemas.d.ts +181 -0
- package/dist/surface/schemas.js +142 -0
- package/dist/surface/schemas.js.map +1 -0
- package/dist/surface/transforms.d.ts +144 -0
- package/dist/surface/transforms.js +120 -0
- package/dist/surface/transforms.js.map +1 -0
- package/dist/surface/types.d.ts +160 -0
- package/dist/surface/types.js +51 -0
- package/dist/surface/types.js.map +1 -0
- package/dist/surface/validation.d.ts +123 -0
- package/dist/surface/validation.js +147 -0
- package/dist/surface/validation.js.map +1 -0
- package/dist/validator.d.ts +55 -0
- package/dist/validator.js +100 -0
- package/dist/validator.js.map +1 -0
- package/package.json +106 -3
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Capability Gate Components
|
|
4
|
+
*
|
|
5
|
+
* Entitlement enforcement at the rendering layer.
|
|
6
|
+
*
|
|
7
|
+
* Provides:
|
|
8
|
+
* - EntitlementProvider: React context for entitlement state
|
|
9
|
+
* - useEntitlements: Hook to read entitlement state
|
|
10
|
+
* - GatedBlockPlaceholder: Visual placeholder for unentitled blocks
|
|
11
|
+
*
|
|
12
|
+
* @module @pwfabric/runtime/render/capability-gate
|
|
13
|
+
*/
|
|
14
|
+
import * as React from 'react';
|
|
15
|
+
// ============================================================
|
|
16
|
+
// CONTEXT
|
|
17
|
+
// ============================================================
|
|
18
|
+
const EntitlementContext = React.createContext({
|
|
19
|
+
loaded: false,
|
|
20
|
+
entitledBlocks: new Set(),
|
|
21
|
+
entitledCapabilities: new Set(),
|
|
22
|
+
isBlockEntitled: () => true, // fail-open when no provider
|
|
23
|
+
isCapabilityEntitled: () => true,
|
|
24
|
+
});
|
|
25
|
+
// ============================================================
|
|
26
|
+
// PROVIDER
|
|
27
|
+
// ============================================================
|
|
28
|
+
/**
|
|
29
|
+
* EntitlementProvider
|
|
30
|
+
*
|
|
31
|
+
* Wraps the app or surface renderer to provide entitlement state.
|
|
32
|
+
* When entitlements is null (not yet loaded), all checks pass (fail-open).
|
|
33
|
+
* Once loaded, enforcement is active.
|
|
34
|
+
*/
|
|
35
|
+
export function EntitlementProvider({ entitlements, children, }) {
|
|
36
|
+
const value = React.useMemo(() => {
|
|
37
|
+
if (!entitlements) {
|
|
38
|
+
return {
|
|
39
|
+
loaded: false,
|
|
40
|
+
entitledBlocks: new Set(),
|
|
41
|
+
entitledCapabilities: new Set(),
|
|
42
|
+
isBlockEntitled: () => true,
|
|
43
|
+
isCapabilityEntitled: () => true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const blocks = new Set(entitlements.blocks);
|
|
47
|
+
const capabilities = new Set(entitlements.capabilities);
|
|
48
|
+
return {
|
|
49
|
+
loaded: true,
|
|
50
|
+
entitledBlocks: blocks,
|
|
51
|
+
entitledCapabilities: capabilities,
|
|
52
|
+
isBlockEntitled: (blockType) => blocks.has(blockType),
|
|
53
|
+
isCapabilityEntitled: (capability) => capabilities.has(capability),
|
|
54
|
+
};
|
|
55
|
+
}, [entitlements]);
|
|
56
|
+
return React.createElement(EntitlementContext.Provider, { value }, children);
|
|
57
|
+
}
|
|
58
|
+
// ============================================================
|
|
59
|
+
// HOOK
|
|
60
|
+
// ============================================================
|
|
61
|
+
/**
|
|
62
|
+
* useEntitlements
|
|
63
|
+
*
|
|
64
|
+
* Read entitlement state from the nearest EntitlementProvider.
|
|
65
|
+
*/
|
|
66
|
+
export function useEntitlements() {
|
|
67
|
+
return React.useContext(EntitlementContext);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* GatedBlockPlaceholder
|
|
71
|
+
*
|
|
72
|
+
* Renders a visual placeholder for blocks the tenant is not entitled to use.
|
|
73
|
+
* Uses inline styles (no Tailwind dependency in runtime package).
|
|
74
|
+
*/
|
|
75
|
+
export function GatedBlockPlaceholder({ blockId, blockType, }) {
|
|
76
|
+
return (_jsxs("div", { "data-block-id": blockId, "data-gated-block": blockType, style: {
|
|
77
|
+
display: 'flex',
|
|
78
|
+
flexDirection: 'column',
|
|
79
|
+
alignItems: 'center',
|
|
80
|
+
justifyContent: 'center',
|
|
81
|
+
padding: '24px 16px',
|
|
82
|
+
// Theme-tokened (was a hardcoded light-gray card that clashed on
|
|
83
|
+
// dark-themed surfaces). The copy stays — this is a deliberate
|
|
84
|
+
// marketplace CTA, not an error message.
|
|
85
|
+
border: '2px dashed var(--pw-color-border, #d1d5db)',
|
|
86
|
+
borderRadius: '8px',
|
|
87
|
+
backgroundColor: 'color-mix(in srgb, var(--pw-color-text, #6b7280) 5%, transparent)',
|
|
88
|
+
color: 'var(--pw-color-text-muted, #6b7280)',
|
|
89
|
+
textAlign: 'center',
|
|
90
|
+
minHeight: '80px',
|
|
91
|
+
gap: '4px',
|
|
92
|
+
}, children: [_jsxs("span", { style: { fontSize: '14px', fontWeight: 500 }, children: ['\u{1F512}', " ", blockType, " block"] }), _jsx("span", { style: { fontSize: '12px', color: 'var(--pw-color-text-muted, #9ca3af)' }, children: "Install from Marketplace" })] }));
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=capability-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-gate.js","sourceRoot":"","sources":["../../src/render/capability-gate.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAwC9B,+DAA+D;AAC/D,UAAU;AACV,+DAA+D;AAE/D,MAAM,kBAAkB,GAAG,KAAK,CAAC,aAAa,CAA0B;IACtE,MAAM,EAAE,KAAK;IACb,cAAc,EAAE,IAAI,GAAG,EAAE;IACzB,oBAAoB,EAAE,IAAI,GAAG,EAAE;IAC/B,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,6BAA6B;IAC1D,oBAAoB,EAAE,GAAG,EAAE,CAAC,IAAI;CACjC,CAAC,CAAA;AAEF,+DAA+D;AAC/D,WAAW;AACX,+DAA+D;AAE/D;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,YAAY,EACZ,QAAQ,GACiB;IACzB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAA0B,GAAG,EAAE;QACxD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO;gBACL,MAAM,EAAE,KAAK;gBACb,cAAc,EAAE,IAAI,GAAG,EAAE;gBACzB,oBAAoB,EAAE,IAAI,GAAG,EAAE;gBAC/B,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI;gBAC3B,oBAAoB,EAAE,GAAG,EAAE,CAAC,IAAI;aACjC,CAAA;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;QAC3C,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,CAAA;QAEvD,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,cAAc,EAAE,MAAM;YACtB,oBAAoB,EAAE,YAAY;YAClC,eAAe,EAAE,CAAC,SAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;YAC7D,oBAAoB,EAAE,CAAC,UAAkB,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC;SAC3E,CAAA;IACH,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAA;IAElB,OAAO,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAA;AAC9E,CAAC;AAED,+DAA+D;AAC/D,OAAO;AACP,+DAA+D;AAE/D;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAA;AAC7C,CAAC;AAWD;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,OAAO,EACP,SAAS,GACkB;IAC3B,OAAO,CACL,gCACiB,OAAO,sBACJ,SAAS,EAC3B,KAAK,EAAE;YACL,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,QAAQ;YACvB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,OAAO,EAAE,WAAW;YACpB,iEAAiE;YACjE,+DAA+D;YAC/D,yCAAyC;YACzC,MAAM,EAAE,4CAA4C;YACpD,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,mEAAmE;YACpF,KAAK,EAAE,qCAAqC;YAC5C,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,MAAM;YACjB,GAAG,EAAE,KAAK;SACX,aAED,gBAAM,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,aAC/C,WAAW,OAAG,SAAS,cACnB,EACP,eAAM,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,qCAAqC,EAAE,yCAAiC,IAC5G,CACP,CAAA;AACH,CAAC","sourcesContent":["/**\n * Capability Gate Components\n *\n * Entitlement enforcement at the rendering layer.\n *\n * Provides:\n * - EntitlementProvider: React context for entitlement state\n * - useEntitlements: Hook to read entitlement state\n * - GatedBlockPlaceholder: Visual placeholder for unentitled blocks\n *\n * @module @pwfabric/runtime/render/capability-gate\n */\n\nimport * as React from 'react'\n\n// ============================================================\n// TYPES\n// ============================================================\n\n/**\n * The claim set this gate reads.\n *\n * Enforcing a claim set is a rendering mechanism; deciding WHO is entitled to\n * WHAT is the host's business. A host's own entitlement type conforms to this\n * shape structurally.\n *\n * Keeping the gate but not the vocabulary is the point: the engine can\n * enforce entitlements for a product it knows nothing about.\n */\nexport interface EntitlementClaims {\n readonly blocks: readonly string[]\n readonly capabilities: readonly string[]\n}\n\nexport interface EntitlementContextValue {\n /** Whether entitlements have been loaded */\n readonly loaded: boolean\n /** Set of entitled block types */\n readonly entitledBlocks: ReadonlySet<string>\n /** Set of entitled capabilities */\n readonly entitledCapabilities: ReadonlySet<string>\n /** Check if a specific block type is entitled */\n readonly isBlockEntitled: (blockType: string) => boolean\n /** Check if a specific capability is entitled */\n readonly isCapabilityEntitled: (capability: string) => boolean\n}\n\nexport interface EntitlementProviderProps {\n /** The claim set from the host, or null if not yet loaded */\n readonly entitlements: EntitlementClaims | null\n readonly children: React.ReactNode\n}\n\n// ============================================================\n// CONTEXT\n// ============================================================\n\nconst EntitlementContext = React.createContext<EntitlementContextValue>({\n loaded: false,\n entitledBlocks: new Set(),\n entitledCapabilities: new Set(),\n isBlockEntitled: () => true, // fail-open when no provider\n isCapabilityEntitled: () => true,\n})\n\n// ============================================================\n// PROVIDER\n// ============================================================\n\n/**\n * EntitlementProvider\n *\n * Wraps the app or surface renderer to provide entitlement state.\n * When entitlements is null (not yet loaded), all checks pass (fail-open).\n * Once loaded, enforcement is active.\n */\nexport function EntitlementProvider({\n entitlements,\n children,\n}: EntitlementProviderProps): React.ReactElement {\n const value = React.useMemo<EntitlementContextValue>(() => {\n if (!entitlements) {\n return {\n loaded: false,\n entitledBlocks: new Set(),\n entitledCapabilities: new Set(),\n isBlockEntitled: () => true,\n isCapabilityEntitled: () => true,\n }\n }\n\n const blocks = new Set(entitlements.blocks)\n const capabilities = new Set(entitlements.capabilities)\n\n return {\n loaded: true,\n entitledBlocks: blocks,\n entitledCapabilities: capabilities,\n isBlockEntitled: (blockType: string) => blocks.has(blockType),\n isCapabilityEntitled: (capability: string) => capabilities.has(capability),\n }\n }, [entitlements])\n\n return React.createElement(EntitlementContext.Provider, { value }, children)\n}\n\n// ============================================================\n// HOOK\n// ============================================================\n\n/**\n * useEntitlements\n *\n * Read entitlement state from the nearest EntitlementProvider.\n */\nexport function useEntitlements(): EntitlementContextValue {\n return React.useContext(EntitlementContext)\n}\n\n// ============================================================\n// GATED BLOCK PLACEHOLDER\n// ============================================================\n\nexport interface GatedBlockPlaceholderProps {\n readonly blockId: string\n readonly blockType: string\n}\n\n/**\n * GatedBlockPlaceholder\n *\n * Renders a visual placeholder for blocks the tenant is not entitled to use.\n * Uses inline styles (no Tailwind dependency in runtime package).\n */\nexport function GatedBlockPlaceholder({\n blockId,\n blockType,\n}: GatedBlockPlaceholderProps): React.ReactElement {\n return (\n <div\n data-block-id={blockId}\n data-gated-block={blockType}\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '24px 16px',\n // Theme-tokened (was a hardcoded light-gray card that clashed on\n // dark-themed surfaces). The copy stays — this is a deliberate\n // marketplace CTA, not an error message.\n border: '2px dashed var(--pw-color-border, #d1d5db)',\n borderRadius: '8px',\n backgroundColor: 'color-mix(in srgb, var(--pw-color-text, #6b7280) 5%, transparent)',\n color: 'var(--pw-color-text-muted, #6b7280)',\n textAlign: 'center',\n minHeight: '80px',\n gap: '4px',\n }}\n >\n <span style={{ fontSize: '14px', fontWeight: 500 }}>\n {'\\u{1F512}'} {blockType} block\n </span>\n <span style={{ fontSize: '12px', color: 'var(--pw-color-text-muted, #9ca3af)' }}>Install from Marketplace</span>\n </div>\n )\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conditional-state CSS generation (aria/data/disabled/checked/`:has(…)` variants).
|
|
3
|
+
*
|
|
4
|
+
* `block.style` sits inline and cannot express pseudo-classes or attribute
|
|
5
|
+
* selectors, and the fixed `block.states` field only covers the three
|
|
6
|
+
* interaction pseudo-classes (`:hover`/`:active`/`:focus-visible`). Everything
|
|
7
|
+
* else a block can style by STATE without JS — form pseudo-classes
|
|
8
|
+
* (`:disabled`, `:checked`, `:invalid`, `:required`), ARIA reflections
|
|
9
|
+
* (`[aria-expanded="true"]`), `data-*` flags (`[data-active]`), and structural
|
|
10
|
+
* `:has(…)` / sibling rules — lives in `block.conditionalStates`. Each entry's
|
|
11
|
+
* `selector` is a CSS suffix APPENDED to the block selector, so the runtime
|
|
12
|
+
* emits:
|
|
13
|
+
*
|
|
14
|
+
* `[data-pw-surface] [data-block-id="<id>"]:disabled{ … }`
|
|
15
|
+
* `[data-pw-surface] [data-block-id="<id>"][aria-expanded="true"]{ … }`
|
|
16
|
+
* `[data-pw-surface] [data-block-id="<id>"]:has(> img){ … }`
|
|
17
|
+
*
|
|
18
|
+
* Keys are CSS camelCase property names (converted to kebab-case); declarations
|
|
19
|
+
* are emitted with `!important` because a block COMPONENT often applies the same
|
|
20
|
+
* CSS property inline with its own default, and inline beats any plain
|
|
21
|
+
* stylesheet rule. Scoped to `[data-block-id]`, so it only overrides the one
|
|
22
|
+
* block. Blocks without `conditionalStates` emit zero bytes so existing surfaces
|
|
23
|
+
* are byte-identical.
|
|
24
|
+
*
|
|
25
|
+
* @module @pwfabric/runtime/render/conditional-states-css
|
|
26
|
+
*/
|
|
27
|
+
import type { Block } from '@pwfabric/core';
|
|
28
|
+
/**
|
|
29
|
+
* Emit the scoped CSS rule(s) for a single block's conditional states. Targets
|
|
30
|
+
* `[data-block-id="<id>"]<selector>` scoped under the surface root so it cannot
|
|
31
|
+
* leak to the host page. Entries with a malformed `selector` (not a valid
|
|
32
|
+
* suffix) or an empty `style` record are skipped. Returns '' when the block
|
|
33
|
+
* declares no usable conditional state.
|
|
34
|
+
*/
|
|
35
|
+
export declare function blockConditionalStatesCss(blockId: string, conditionalStates: NonNullable<Block['conditionalStates']>, surfaceId?: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Walk a surface block tree and concatenate the per-block conditional-state CSS
|
|
38
|
+
* for every block declaring `conditionalStates`. Blocks without it are skipped
|
|
39
|
+
* (zero bytes emitted) so existing surfaces are byte-identical.
|
|
40
|
+
*/
|
|
41
|
+
export declare function collectConditionalStatesCss(blocks: readonly Block[], surfaceId?: string): string;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conditional-state CSS generation (aria/data/disabled/checked/`:has(…)` variants).
|
|
3
|
+
*
|
|
4
|
+
* `block.style` sits inline and cannot express pseudo-classes or attribute
|
|
5
|
+
* selectors, and the fixed `block.states` field only covers the three
|
|
6
|
+
* interaction pseudo-classes (`:hover`/`:active`/`:focus-visible`). Everything
|
|
7
|
+
* else a block can style by STATE without JS — form pseudo-classes
|
|
8
|
+
* (`:disabled`, `:checked`, `:invalid`, `:required`), ARIA reflections
|
|
9
|
+
* (`[aria-expanded="true"]`), `data-*` flags (`[data-active]`), and structural
|
|
10
|
+
* `:has(…)` / sibling rules — lives in `block.conditionalStates`. Each entry's
|
|
11
|
+
* `selector` is a CSS suffix APPENDED to the block selector, so the runtime
|
|
12
|
+
* emits:
|
|
13
|
+
*
|
|
14
|
+
* `[data-pw-surface] [data-block-id="<id>"]:disabled{ … }`
|
|
15
|
+
* `[data-pw-surface] [data-block-id="<id>"][aria-expanded="true"]{ … }`
|
|
16
|
+
* `[data-pw-surface] [data-block-id="<id>"]:has(> img){ … }`
|
|
17
|
+
*
|
|
18
|
+
* Keys are CSS camelCase property names (converted to kebab-case); declarations
|
|
19
|
+
* are emitted with `!important` because a block COMPONENT often applies the same
|
|
20
|
+
* CSS property inline with its own default, and inline beats any plain
|
|
21
|
+
* stylesheet rule. Scoped to `[data-block-id]`, so it only overrides the one
|
|
22
|
+
* block. Blocks without `conditionalStates` emit zero bytes so existing surfaces
|
|
23
|
+
* are byte-identical.
|
|
24
|
+
*
|
|
25
|
+
* @module @pwfabric/runtime/render/conditional-states-css
|
|
26
|
+
*/
|
|
27
|
+
import { blockSelector, camelToKebab, collectScopedCss } from './scoped-css.js';
|
|
28
|
+
/** Serialize a camelCase decl record to `prop:value !important;…` (values pass through). */
|
|
29
|
+
function declsToCss(decls) {
|
|
30
|
+
return Object.entries(decls)
|
|
31
|
+
.map(([prop, value]) => `${camelToKebab(prop)}:${value} !important`)
|
|
32
|
+
.join(';');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A conditional-state selector must be a SUFFIX that attaches directly to the
|
|
36
|
+
* block selector — never a bare/standalone selector that could match (and leak
|
|
37
|
+
* to) unrelated elements on the host page. Valid first characters:
|
|
38
|
+
* `:` pseudo-class/element (`:disabled`, `:has(…)`)
|
|
39
|
+
* `[` attribute selector (`[aria-expanded="true"]`, `[data-active]`)
|
|
40
|
+
* `>` `+` `~` combinators (`> img`, `+ .x`, `~ .y`)
|
|
41
|
+
* whitespace — descendant combinator (` .child`)
|
|
42
|
+
* Anything else (a bare `.class`, `div`, `*`, empty string) is rejected.
|
|
43
|
+
*/
|
|
44
|
+
function isValidSuffixSelector(selector) {
|
|
45
|
+
if (typeof selector !== 'string' || selector.length === 0)
|
|
46
|
+
return false;
|
|
47
|
+
const first = selector.charAt(0);
|
|
48
|
+
return first === ':' || first === '[' || first === '>' || first === '+' || first === '~' || /\s/.test(first);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Emit the scoped CSS rule(s) for a single block's conditional states. Targets
|
|
52
|
+
* `[data-block-id="<id>"]<selector>` scoped under the surface root so it cannot
|
|
53
|
+
* leak to the host page. Entries with a malformed `selector` (not a valid
|
|
54
|
+
* suffix) or an empty `style` record are skipped. Returns '' when the block
|
|
55
|
+
* declares no usable conditional state.
|
|
56
|
+
*/
|
|
57
|
+
export function blockConditionalStatesCss(blockId, conditionalStates, surfaceId) {
|
|
58
|
+
const selector = blockSelector(blockId, surfaceId);
|
|
59
|
+
let css = '';
|
|
60
|
+
for (const entry of conditionalStates) {
|
|
61
|
+
if (!entry || !isValidSuffixSelector(entry.selector))
|
|
62
|
+
continue;
|
|
63
|
+
const decls = entry.style;
|
|
64
|
+
if (!decls || Object.keys(decls).length === 0)
|
|
65
|
+
continue;
|
|
66
|
+
// Same wrapper-exclusion as states-css: the id matches two elements; the
|
|
67
|
+
// visual rule must land on the component root, not the square wrapper.
|
|
68
|
+
css += `${selector}:not([data-block-wrapper])${entry.selector}{${declsToCss(decls)}}`;
|
|
69
|
+
}
|
|
70
|
+
return css;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Walk a surface block tree and concatenate the per-block conditional-state CSS
|
|
74
|
+
* for every block declaring `conditionalStates`. Blocks without it are skipped
|
|
75
|
+
* (zero bytes emitted) so existing surfaces are byte-identical.
|
|
76
|
+
*/
|
|
77
|
+
export function collectConditionalStatesCss(blocks, surfaceId) {
|
|
78
|
+
return collectScopedCss(blocks, (block) => block.conditionalStates
|
|
79
|
+
? blockConditionalStatesCss(block.id, block.conditionalStates, surfaceId)
|
|
80
|
+
: '');
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=conditional-states-css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditional-states-css.js","sourceRoot":"","sources":["../../src/render/conditional-states-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAE/E,4FAA4F;AAC5F,SAAS,UAAU,CAAC,KAAuC;IACzD,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SACzB,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,KAAK,aAAa,CAAC;SACnE,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,qBAAqB,CAAC,QAAgB;IAC7C,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACvE,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAChC,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAC9G,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAe,EACf,iBAA0D,EAC1D,SAAkB;IAElB,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IAClD,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,KAAK,MAAM,KAAK,IAAI,iBAAiB,EAAE,CAAC;QACtC,IAAI,CAAC,KAAK,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,SAAQ;QAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;QACzB,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QACvD,yEAAyE;QACzE,uEAAuE;QACvE,GAAG,IAAI,GAAG,QAAQ,6BAA6B,KAAK,CAAC,QAAQ,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAA;IACvF,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAwB,EAAE,SAAkB;IACtF,OAAO,gBAAgB,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CACxC,KAAK,CAAC,iBAAiB;QACrB,CAAC,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,iBAAiB,EAAE,SAAS,CAAC;QACzE,CAAC,CAAC,EAAE,CACP,CAAA;AACH,CAAC","sourcesContent":["/**\n * Conditional-state CSS generation (aria/data/disabled/checked/`:has(…)` variants).\n *\n * `block.style` sits inline and cannot express pseudo-classes or attribute\n * selectors, and the fixed `block.states` field only covers the three\n * interaction pseudo-classes (`:hover`/`:active`/`:focus-visible`). Everything\n * else a block can style by STATE without JS — form pseudo-classes\n * (`:disabled`, `:checked`, `:invalid`, `:required`), ARIA reflections\n * (`[aria-expanded=\"true\"]`), `data-*` flags (`[data-active]`), and structural\n * `:has(…)` / sibling rules — lives in `block.conditionalStates`. Each entry's\n * `selector` is a CSS suffix APPENDED to the block selector, so the runtime\n * emits:\n *\n * `[data-pw-surface] [data-block-id=\"<id>\"]:disabled{ … }`\n * `[data-pw-surface] [data-block-id=\"<id>\"][aria-expanded=\"true\"]{ … }`\n * `[data-pw-surface] [data-block-id=\"<id>\"]:has(> img){ … }`\n *\n * Keys are CSS camelCase property names (converted to kebab-case); declarations\n * are emitted with `!important` because a block COMPONENT often applies the same\n * CSS property inline with its own default, and inline beats any plain\n * stylesheet rule. Scoped to `[data-block-id]`, so it only overrides the one\n * block. Blocks without `conditionalStates` emit zero bytes so existing surfaces\n * are byte-identical.\n *\n * @module @pwfabric/runtime/render/conditional-states-css\n */\n\nimport type { Block } from '@pwfabric/core'\nimport { blockSelector, camelToKebab, collectScopedCss } from './scoped-css.js'\n\n/** Serialize a camelCase decl record to `prop:value !important;…` (values pass through). */\nfunction declsToCss(decls: Readonly<Record<string, string>>): string {\n return Object.entries(decls)\n .map(([prop, value]) => `${camelToKebab(prop)}:${value} !important`)\n .join(';')\n}\n\n/**\n * A conditional-state selector must be a SUFFIX that attaches directly to the\n * block selector — never a bare/standalone selector that could match (and leak\n * to) unrelated elements on the host page. Valid first characters:\n * `:` pseudo-class/element (`:disabled`, `:has(…)`)\n * `[` attribute selector (`[aria-expanded=\"true\"]`, `[data-active]`)\n * `>` `+` `~` combinators (`> img`, `+ .x`, `~ .y`)\n * whitespace — descendant combinator (` .child`)\n * Anything else (a bare `.class`, `div`, `*`, empty string) is rejected.\n */\nfunction isValidSuffixSelector(selector: string): boolean {\n if (typeof selector !== 'string' || selector.length === 0) return false\n const first = selector.charAt(0)\n return first === ':' || first === '[' || first === '>' || first === '+' || first === '~' || /\\s/.test(first)\n}\n\n/**\n * Emit the scoped CSS rule(s) for a single block's conditional states. Targets\n * `[data-block-id=\"<id>\"]<selector>` scoped under the surface root so it cannot\n * leak to the host page. Entries with a malformed `selector` (not a valid\n * suffix) or an empty `style` record are skipped. Returns '' when the block\n * declares no usable conditional state.\n */\nexport function blockConditionalStatesCss(\n blockId: string,\n conditionalStates: NonNullable<Block['conditionalStates']>,\n surfaceId?: string\n): string {\n const selector = blockSelector(blockId, surfaceId)\n let css = ''\n for (const entry of conditionalStates) {\n if (!entry || !isValidSuffixSelector(entry.selector)) continue\n const decls = entry.style\n if (!decls || Object.keys(decls).length === 0) continue\n // Same wrapper-exclusion as states-css: the id matches two elements; the\n // visual rule must land on the component root, not the square wrapper.\n css += `${selector}:not([data-block-wrapper])${entry.selector}{${declsToCss(decls)}}`\n }\n return css\n}\n\n/**\n * Walk a surface block tree and concatenate the per-block conditional-state CSS\n * for every block declaring `conditionalStates`. Blocks without it are skipped\n * (zero bytes emitted) so existing surfaces are byte-identical.\n */\nexport function collectConditionalStatesCss(blocks: readonly Block[], surfaceId?: string): string {\n return collectScopedCss(blocks, (block) =>\n block.conditionalStates\n ? blockConditionalStatesCss(block.id, block.conditionalStates, surfaceId)\n : ''\n )\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface Connections React Context
|
|
3
|
+
*
|
|
4
|
+
* Carries the surface's CONNECTIONS CONTEXT — the world's configured
|
|
5
|
+
* connections (name/connector/config, single dialect with the runner's
|
|
6
|
+
* `connections.json` entries) plus the loaded engine registry — through
|
|
7
|
+
* the render tree. Pattern mirrors `EntityFacadeContext`.
|
|
8
|
+
*
|
|
9
|
+
* Consumers:
|
|
10
|
+
* - `DataBoundSurfaceRenderer` routes `{kind:'entity', connector}` data
|
|
11
|
+
* sources through the registry (via the renderer prop, not this context
|
|
12
|
+
* — the fetch runs above `SurfaceRenderer`).
|
|
13
|
+
* - Pack blocks on the engine-bridge path read connections/config here
|
|
14
|
+
* (platform source) instead of the runner's bundled connections.json —
|
|
15
|
+
* same shape, different source.
|
|
16
|
+
*
|
|
17
|
+
* Absent provider = null = today's behavior (additive, opt-in).
|
|
18
|
+
*
|
|
19
|
+
* @module @pwfabric/runtime/render/connections-context
|
|
20
|
+
*/
|
|
21
|
+
import type { SurfaceConnectionsValue } from '../connectors/types.js';
|
|
22
|
+
/**
|
|
23
|
+
* React context carrying the connections context. Defaults to null —
|
|
24
|
+
* hosts that don't provide it keep today's behavior everywhere.
|
|
25
|
+
*/
|
|
26
|
+
export declare const SurfaceConnectionsContext: import("react").Context<SurfaceConnectionsValue | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Returns the connections context from the nearest provider, or null when
|
|
29
|
+
* the host didn't opt in (runner default path, legacy platform rendering).
|
|
30
|
+
*/
|
|
31
|
+
export declare function useSurfaceConnections(): SurfaceConnectionsValue | null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface Connections React Context
|
|
3
|
+
*
|
|
4
|
+
* Carries the surface's CONNECTIONS CONTEXT — the world's configured
|
|
5
|
+
* connections (name/connector/config, single dialect with the runner's
|
|
6
|
+
* `connections.json` entries) plus the loaded engine registry — through
|
|
7
|
+
* the render tree. Pattern mirrors `EntityFacadeContext`.
|
|
8
|
+
*
|
|
9
|
+
* Consumers:
|
|
10
|
+
* - `DataBoundSurfaceRenderer` routes `{kind:'entity', connector}` data
|
|
11
|
+
* sources through the registry (via the renderer prop, not this context
|
|
12
|
+
* — the fetch runs above `SurfaceRenderer`).
|
|
13
|
+
* - Pack blocks on the engine-bridge path read connections/config here
|
|
14
|
+
* (platform source) instead of the runner's bundled connections.json —
|
|
15
|
+
* same shape, different source.
|
|
16
|
+
*
|
|
17
|
+
* Absent provider = null = today's behavior (additive, opt-in).
|
|
18
|
+
*
|
|
19
|
+
* @module @pwfabric/runtime/render/connections-context
|
|
20
|
+
*/
|
|
21
|
+
import { createContext, useContext } from 'react';
|
|
22
|
+
/**
|
|
23
|
+
* React context carrying the connections context. Defaults to null —
|
|
24
|
+
* hosts that don't provide it keep today's behavior everywhere.
|
|
25
|
+
*/
|
|
26
|
+
export const SurfaceConnectionsContext = createContext(null);
|
|
27
|
+
/**
|
|
28
|
+
* Returns the connections context from the nearest provider, or null when
|
|
29
|
+
* the host didn't opt in (runner default path, legacy platform rendering).
|
|
30
|
+
*/
|
|
31
|
+
export function useSurfaceConnections() {
|
|
32
|
+
return useContext(SurfaceConnectionsContext);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=connections-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections-context.js","sourceRoot":"","sources":["../../src/render/connections-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAGjD;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,aAAa,CAAiC,IAAI,CAAC,CAAA;AAE5F;;;GAGG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,UAAU,CAAC,yBAAyB,CAAC,CAAA;AAC9C,CAAC","sourcesContent":["/**\n * Surface Connections React Context\n *\n * Carries the surface's CONNECTIONS CONTEXT — the world's configured\n * connections (name/connector/config, single dialect with the runner's\n * `connections.json` entries) plus the loaded engine registry — through\n * the render tree. Pattern mirrors `EntityFacadeContext`.\n *\n * Consumers:\n * - `DataBoundSurfaceRenderer` routes `{kind:'entity', connector}` data\n * sources through the registry (via the renderer prop, not this context\n * — the fetch runs above `SurfaceRenderer`).\n * - Pack blocks on the engine-bridge path read connections/config here\n * (platform source) instead of the runner's bundled connections.json —\n * same shape, different source.\n *\n * Absent provider = null = today's behavior (additive, opt-in).\n *\n * @module @pwfabric/runtime/render/connections-context\n */\n\nimport { createContext, useContext } from 'react'\nimport type { SurfaceConnectionsValue } from '../connectors/types.js'\n\n/**\n * React context carrying the connections context. Defaults to null —\n * hosts that don't provide it keep today's behavior everywhere.\n */\nexport const SurfaceConnectionsContext = createContext<SurfaceConnectionsValue | null>(null)\n\n/**\n * Returns the connections context from the nearest provider, or null when\n * the host didn't opt in (runner default path, legacy platform rendering).\n */\nexport function useSurfaceConnections(): SurfaceConnectionsValue | null {\n return useContext(SurfaceConnectionsContext)\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dark theme variant CSS generation (the "both strategies" dark mode).
|
|
3
|
+
*
|
|
4
|
+
* Light theme tokens stay INLINE on the surface root (`[data-pw-surface]`); this
|
|
5
|
+
* module emits the scoped rules that override them under TWO conditions:
|
|
6
|
+
*
|
|
7
|
+
* 1. Manual force-dark — `[data-pw-surface="<sid>"][data-pw-theme="dark"]{…}`
|
|
8
|
+
* (host toggles `data-pw-theme="dark"` on the root regardless of OS).
|
|
9
|
+
* 2. Auto (OS preference) — `@media (prefers-color-scheme:dark){
|
|
10
|
+
* [data-pw-surface="<sid>"]:not([data-pw-theme="light"]){…}}` (applies
|
|
11
|
+
* unless the host has force-toggled light).
|
|
12
|
+
*
|
|
13
|
+
* The selector carries the surface ID by VALUE. It used to match on the mere
|
|
14
|
+
* PRESENCE of `[data-pw-surface]`, which was a real bug: the embed autoloader
|
|
15
|
+
* hydrates every `[data-pw-surface]` element in a document, so a host page can
|
|
16
|
+
* hold several surfaces with different palettes. Each emitted its own `<style>`
|
|
17
|
+
* with the same value-less selector and `!important`, so equal specificity made
|
|
18
|
+
* DOCUMENT ORDER decide — the last surface's dark palette repainted all of them.
|
|
19
|
+
* Reproduced in Chromium: a blue-themed surface rendered the amber surface's
|
|
20
|
+
* dark background. The light theme was never affected because its values are
|
|
21
|
+
* inline per element and custom properties inherit.
|
|
22
|
+
*
|
|
23
|
+
* @module @pwfabric/runtime/render/dark-theme-css
|
|
24
|
+
*/
|
|
25
|
+
import type { AppearanceModePolicy } from '@pwfabric/contracts';
|
|
26
|
+
/**
|
|
27
|
+
* Build the dark theme CSS from a resolved dark CSS-variable map (the output of
|
|
28
|
+
* `resolveAppearanceDarkVars`). Emits BOTH the manual force-dark rule and the
|
|
29
|
+
* `prefers-color-scheme:dark` auto rule. Returns '' when there are no dark vars.
|
|
30
|
+
*
|
|
31
|
+
* @param darkVars - resolved `--pw-*` map for the dark variant
|
|
32
|
+
* @param surfaceId - scopes the rules to ONE surface. Omit only when rendering a
|
|
33
|
+
* single surface in isolation (unit tests); the renderer always supplies it,
|
|
34
|
+
* because two surfaces sharing a document must not share a dark palette.
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildDarkThemeCss(darkVars: Record<string, string>, surfaceId?: string, policy?: AppearanceModePolicy): string;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dark theme variant CSS generation (the "both strategies" dark mode).
|
|
3
|
+
*
|
|
4
|
+
* Light theme tokens stay INLINE on the surface root (`[data-pw-surface]`); this
|
|
5
|
+
* module emits the scoped rules that override them under TWO conditions:
|
|
6
|
+
*
|
|
7
|
+
* 1. Manual force-dark — `[data-pw-surface="<sid>"][data-pw-theme="dark"]{…}`
|
|
8
|
+
* (host toggles `data-pw-theme="dark"` on the root regardless of OS).
|
|
9
|
+
* 2. Auto (OS preference) — `@media (prefers-color-scheme:dark){
|
|
10
|
+
* [data-pw-surface="<sid>"]:not([data-pw-theme="light"]){…}}` (applies
|
|
11
|
+
* unless the host has force-toggled light).
|
|
12
|
+
*
|
|
13
|
+
* The selector carries the surface ID by VALUE. It used to match on the mere
|
|
14
|
+
* PRESENCE of `[data-pw-surface]`, which was a real bug: the embed autoloader
|
|
15
|
+
* hydrates every `[data-pw-surface]` element in a document, so a host page can
|
|
16
|
+
* hold several surfaces with different palettes. Each emitted its own `<style>`
|
|
17
|
+
* with the same value-less selector and `!important`, so equal specificity made
|
|
18
|
+
* DOCUMENT ORDER decide — the last surface's dark palette repainted all of them.
|
|
19
|
+
* Reproduced in Chromium: a blue-themed surface rendered the amber surface's
|
|
20
|
+
* dark background. The light theme was never affected because its values are
|
|
21
|
+
* inline per element and custom properties inherit.
|
|
22
|
+
*
|
|
23
|
+
* @module @pwfabric/runtime/render/dark-theme-css
|
|
24
|
+
*/
|
|
25
|
+
import { surfaceScope } from './scoped-css.js';
|
|
26
|
+
/**
|
|
27
|
+
* Serialize a `--pw-*` CSS-var map to `--pw-…:val !important;…`.
|
|
28
|
+
* `!important`: the LIGHT theme vars are applied INLINE on the surface root
|
|
29
|
+
* (`rootStyle`), and an inline declaration beats any stylesheet/@media rule — so
|
|
30
|
+
* without `!important` the dark overrides would never take effect. `!important`
|
|
31
|
+
* on a custom-property declaration is honoured by the cascade and lets the
|
|
32
|
+
* stylesheet dark vars override the inline light vars.
|
|
33
|
+
*/
|
|
34
|
+
function varsToCss(vars) {
|
|
35
|
+
return Object.entries(vars)
|
|
36
|
+
.map(([name, value]) => `${name}:${value} !important`)
|
|
37
|
+
.join(';');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Build the dark theme CSS from a resolved dark CSS-variable map (the output of
|
|
41
|
+
* `resolveAppearanceDarkVars`). Emits BOTH the manual force-dark rule and the
|
|
42
|
+
* `prefers-color-scheme:dark` auto rule. Returns '' when there are no dark vars.
|
|
43
|
+
*
|
|
44
|
+
* @param darkVars - resolved `--pw-*` map for the dark variant
|
|
45
|
+
* @param surfaceId - scopes the rules to ONE surface. Omit only when rendering a
|
|
46
|
+
* single surface in isolation (unit tests); the renderer always supplies it,
|
|
47
|
+
* because two surfaces sharing a document must not share a dark palette.
|
|
48
|
+
*/
|
|
49
|
+
export function buildDarkThemeCss(darkVars, surfaceId, policy = 'system') {
|
|
50
|
+
// The app says which modes it wears. A light-only app emits no
|
|
51
|
+
// dark rule at all, so a dark device keeps it light; a dark-only app wears the
|
|
52
|
+
// dark palette unconditionally. `system` follows the device.
|
|
53
|
+
if (policy === 'light')
|
|
54
|
+
return '';
|
|
55
|
+
const body = varsToCss(darkVars);
|
|
56
|
+
if (!body)
|
|
57
|
+
return '';
|
|
58
|
+
const scope = surfaceScope(surfaceId);
|
|
59
|
+
if (policy === 'dark')
|
|
60
|
+
return `${scope}{${body}}`;
|
|
61
|
+
// 1. Manual force-dark (host sets data-pw-theme="dark").
|
|
62
|
+
const manual = `${scope}[data-pw-theme="dark"]{${body}}`;
|
|
63
|
+
// 2. Auto via OS preference, unless force-light (data-pw-theme="light").
|
|
64
|
+
const auto = `@media (prefers-color-scheme:dark){${scope}:not([data-pw-theme="light"]){${body}}}`;
|
|
65
|
+
return manual + auto;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=dark-theme-css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dark-theme-css.js","sourceRoot":"","sources":["../../src/render/dark-theme-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C;;;;;;;GAOG;AACH,SAAS,SAAS,CAAC,IAA4B;IAC7C,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;SACxB,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,KAAK,aAAa,CAAC;SACrD,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAgC,EAChC,SAAkB,EAClB,SAA+B,QAAQ;IAEvC,+DAA+D;IAC/D,+EAA+E;IAC/E,6DAA6D;IAC7D,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,EAAE,CAAA;IACjC,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;IAChC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAA;IACpB,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA;IACrC,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,CAAA;IACjD,yDAAyD;IACzD,MAAM,MAAM,GAAG,GAAG,KAAK,0BAA0B,IAAI,GAAG,CAAA;IACxD,yEAAyE;IACzE,MAAM,IAAI,GAAG,sCAAsC,KAAK,iCAAiC,IAAI,IAAI,CAAA;IACjG,OAAO,MAAM,GAAG,IAAI,CAAA;AACtB,CAAC","sourcesContent":["/**\n * Dark theme variant CSS generation (the \"both strategies\" dark mode).\n *\n * Light theme tokens stay INLINE on the surface root (`[data-pw-surface]`); this\n * module emits the scoped rules that override them under TWO conditions:\n *\n * 1. Manual force-dark — `[data-pw-surface=\"<sid>\"][data-pw-theme=\"dark\"]{…}`\n * (host toggles `data-pw-theme=\"dark\"` on the root regardless of OS).\n * 2. Auto (OS preference) — `@media (prefers-color-scheme:dark){\n * [data-pw-surface=\"<sid>\"]:not([data-pw-theme=\"light\"]){…}}` (applies\n * unless the host has force-toggled light).\n *\n * The selector carries the surface ID by VALUE. It used to match on the mere\n * PRESENCE of `[data-pw-surface]`, which was a real bug: the embed autoloader\n * hydrates every `[data-pw-surface]` element in a document, so a host page can\n * hold several surfaces with different palettes. Each emitted its own `<style>`\n * with the same value-less selector and `!important`, so equal specificity made\n * DOCUMENT ORDER decide — the last surface's dark palette repainted all of them.\n * Reproduced in Chromium: a blue-themed surface rendered the amber surface's\n * dark background. The light theme was never affected because its values are\n * inline per element and custom properties inherit.\n *\n * @module @pwfabric/runtime/render/dark-theme-css\n */\n\nimport type { AppearanceModePolicy } from '@pwfabric/contracts'\nimport { surfaceScope } from './scoped-css.js'\n\n/**\n * Serialize a `--pw-*` CSS-var map to `--pw-…:val !important;…`.\n * `!important`: the LIGHT theme vars are applied INLINE on the surface root\n * (`rootStyle`), and an inline declaration beats any stylesheet/@media rule — so\n * without `!important` the dark overrides would never take effect. `!important`\n * on a custom-property declaration is honoured by the cascade and lets the\n * stylesheet dark vars override the inline light vars.\n */\nfunction varsToCss(vars: Record<string, string>): string {\n return Object.entries(vars)\n .map(([name, value]) => `${name}:${value} !important`)\n .join(';')\n}\n\n/**\n * Build the dark theme CSS from a resolved dark CSS-variable map (the output of\n * `resolveAppearanceDarkVars`). Emits BOTH the manual force-dark rule and the\n * `prefers-color-scheme:dark` auto rule. Returns '' when there are no dark vars.\n *\n * @param darkVars - resolved `--pw-*` map for the dark variant\n * @param surfaceId - scopes the rules to ONE surface. Omit only when rendering a\n * single surface in isolation (unit tests); the renderer always supplies it,\n * because two surfaces sharing a document must not share a dark palette.\n */\nexport function buildDarkThemeCss(\n darkVars: Record<string, string>,\n surfaceId?: string,\n policy: AppearanceModePolicy = 'system'\n): string {\n // The app says which modes it wears. A light-only app emits no\n // dark rule at all, so a dark device keeps it light; a dark-only app wears the\n // dark palette unconditionally. `system` follows the device.\n if (policy === 'light') return ''\n const body = varsToCss(darkVars)\n if (!body) return ''\n const scope = surfaceScope(surfaceId)\n if (policy === 'dark') return `${scope}{${body}}`\n // 1. Manual force-dark (host sets data-pw-theme=\"dark\").\n const manual = `${scope}[data-pw-theme=\"dark\"]{${body}}`\n // 2. Auto via OS preference, unless force-light (data-pw-theme=\"light\").\n const auto = `@media (prefers-color-scheme:dark){${scope}:not([data-pw-theme=\"light\"]){${body}}}`\n return manual + auto\n}\n"]}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data Binding Types for Surface Renderer
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for data-bound surface rendering.
|
|
5
|
+
* These types define the shape of surface JSON definitions that include
|
|
6
|
+
* dataSources, state, and expression-based prop bindings.
|
|
7
|
+
*
|
|
8
|
+
* @module @pwfabric/runtime/render/data-binding-types
|
|
9
|
+
*/
|
|
10
|
+
import type { SurfaceDataCache } from './data-cache.js';
|
|
11
|
+
import type { Block } from '@pwfabric/core';
|
|
12
|
+
import type { RenderableSurface, SurfaceRendererProps } from './types.js';
|
|
13
|
+
import type { DataServiceConfig } from '../data/types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Source kinds supported in surface JSON definitions.
|
|
16
|
+
* Note: 'computed' is excluded because functions can't be serialized in JSON.
|
|
17
|
+
*/
|
|
18
|
+
export type SurfaceDataSourceKind = 'rest' | 'static' | 'state' | 'entity';
|
|
19
|
+
/**
|
|
20
|
+
* Data source definition within a surface JSON.
|
|
21
|
+
* Unlike DataSourceDefinition from data/types, this is JSON-serializable.
|
|
22
|
+
*/
|
|
23
|
+
export interface SurfaceDataSourceDefinition {
|
|
24
|
+
/** Unique source identifier, used as the key in expression context */
|
|
25
|
+
readonly id: string;
|
|
26
|
+
/** Source kind */
|
|
27
|
+
readonly kind: SurfaceDataSourceKind;
|
|
28
|
+
/** REST endpoint (may contain {{state.key}} placeholders) */
|
|
29
|
+
readonly endpoint?: string;
|
|
30
|
+
/** HTTP method for REST sources */
|
|
31
|
+
readonly method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
32
|
+
/** Static inline data */
|
|
33
|
+
readonly staticData?: unknown;
|
|
34
|
+
/** Auto-refresh interval in ms (0 or undefined = no auto-refresh) */
|
|
35
|
+
readonly refreshInterval?: number;
|
|
36
|
+
/** Optional HTTP headers to include in REST requests (e.g. Authorization) */
|
|
37
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
38
|
+
/** Entity type to list (kind: 'entity') via the platform/entities facade */
|
|
39
|
+
readonly entityType?: string;
|
|
40
|
+
/** Optional query for entity sources (filter/sort/pagination). String
|
|
41
|
+
* leaves may carry `{{state.x}}` expressions — resolved against surface
|
|
42
|
+
* state before the connector is called (see render/query-state.ts). */
|
|
43
|
+
readonly query?: Readonly<Record<string, unknown>>;
|
|
44
|
+
/** Payload bound when the source cannot be served (connector missing /
|
|
45
|
+
* failed). `__errors.<id>` stays populated alongside it. */
|
|
46
|
+
readonly fallback?: unknown;
|
|
47
|
+
/**
|
|
48
|
+
* Contract parity with `dataSourceSchema.connector`: which
|
|
49
|
+
* data-plane engine serves this entity source (e.g. 'graph-lists').
|
|
50
|
+
* Routed through the host-provided `ConnectorEngineRegistry` when the
|
|
51
|
+
* connection is registered there; absent/unregistered = the default
|
|
52
|
+
* entity facade path (today's behavior).
|
|
53
|
+
*/
|
|
54
|
+
readonly connector?: string;
|
|
55
|
+
/**
|
|
56
|
+
* The response property holding the list — `data`, `products`, or absent
|
|
57
|
+
* when the body IS the array. Dotted paths allowed for a nested one.
|
|
58
|
+
*/
|
|
59
|
+
readonly returns?: string;
|
|
60
|
+
/** world auth binding BY NAME — never credential values. */
|
|
61
|
+
readonly authProviderRef?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Contract parity with `dataSourceSchema.aggregate`: ask for ONE
|
|
64
|
+
* NUMBER over the collection instead of its rows. The source binds
|
|
65
|
+
* `{ fn, field?, value, count }` — `{{<id>.value}}` — and is exempt from
|
|
66
|
+
* the list wrap. `filter` leaves may carry `{{state.x}}` like `query`.
|
|
67
|
+
*/
|
|
68
|
+
readonly aggregate?: {
|
|
69
|
+
readonly fn: 'count' | 'sum' | 'avg';
|
|
70
|
+
readonly field?: string;
|
|
71
|
+
readonly filter?: Readonly<Record<string, unknown>>;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Action types that blocks can dispatch via their action prop.
|
|
76
|
+
*/
|
|
77
|
+
export type SurfaceActionType = 'setState' | 'refresh' | 'refreshAll' | 'showBlock' | 'hideBlock' | 'navigate';
|
|
78
|
+
/**
|
|
79
|
+
* Action dispatched by a block (e.g. button click, tab change).
|
|
80
|
+
*/
|
|
81
|
+
export type SurfaceAction = {
|
|
82
|
+
readonly type: 'setState';
|
|
83
|
+
readonly key: string;
|
|
84
|
+
readonly value: unknown;
|
|
85
|
+
} | {
|
|
86
|
+
readonly type: 'refresh';
|
|
87
|
+
readonly sourceId: string;
|
|
88
|
+
} | {
|
|
89
|
+
readonly type: 'refreshAll';
|
|
90
|
+
} | {
|
|
91
|
+
readonly type: 'showBlock';
|
|
92
|
+
readonly blockId: string;
|
|
93
|
+
} | {
|
|
94
|
+
readonly type: 'hideBlock';
|
|
95
|
+
readonly blockId: string;
|
|
96
|
+
} | {
|
|
97
|
+
readonly type: 'navigate';
|
|
98
|
+
readonly url: string;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* What a block's `action` prop may hold: one action, or a list run in order
|
|
102
|
+
* on the block's click (`block:click`) — never on its other events.
|
|
103
|
+
*/
|
|
104
|
+
export type BlockActionProp = SurfaceAction | readonly SurfaceAction[];
|
|
105
|
+
/**
|
|
106
|
+
* A behavior stored on a published surface — maps an event trigger to one or more actions.
|
|
107
|
+
* The `event` field accepts canonical colon form (`block:click`) or legacy dot form
|
|
108
|
+
* (`surface.load`) — normalized at match time by `canonicalizeEventType`.
|
|
109
|
+
*/
|
|
110
|
+
export interface RuntimeBehavior {
|
|
111
|
+
readonly id: string;
|
|
112
|
+
readonly event: string;
|
|
113
|
+
readonly targetBlockId?: string;
|
|
114
|
+
readonly actions: readonly SurfaceAction[];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Surface definition extended with data binding capabilities.
|
|
118
|
+
* This is the shape of a surface JSON that uses live data.
|
|
119
|
+
*/
|
|
120
|
+
export interface DataBoundSurface {
|
|
121
|
+
/**
|
|
122
|
+
* Stable surface id — SurfaceRenderer's render scope.
|
|
123
|
+
*
|
|
124
|
+
* Omitted from this type originally, which made the drop invisible: the
|
|
125
|
+
* renderer decomposes the surface into blocks/appearance/capabilities and
|
|
126
|
+
* rebuilds it, and a field the type never had could not survive the rebuild.
|
|
127
|
+
* Downstream, `[data-pw-surface]` rendered with an EMPTY value and every
|
|
128
|
+
* per-surface rule (dark theme, visibility, interaction states) fell back to
|
|
129
|
+
* the value-less selector shared by every surface in the document — the exact
|
|
130
|
+
* collision the scoping was added to prevent.
|
|
131
|
+
*/
|
|
132
|
+
readonly id?: string;
|
|
133
|
+
/** Block composition */
|
|
134
|
+
readonly blocks: readonly Block[];
|
|
135
|
+
/** ui-appearance atom reference (theme + layout + styleVariables consolidated). */
|
|
136
|
+
readonly appearance?: RenderableSurface['appearance'];
|
|
137
|
+
/** capability list — `platform/persistence` carries dataSources + initialState in its config. */
|
|
138
|
+
readonly capabilities?: RenderableSurface['capabilities'];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Props for DataBoundSurfaceRenderer.
|
|
142
|
+
* Extends SurfaceRendererProps but accepts a DataBoundSurface.
|
|
143
|
+
*/
|
|
144
|
+
export interface DataBoundSurfaceRendererProps extends Omit<SurfaceRendererProps, 'surface'> {
|
|
145
|
+
/** Surface definition with optional dataSources and state */
|
|
146
|
+
readonly surface: DataBoundSurface;
|
|
147
|
+
/** Stored behaviors to execute when their trigger event fires on the bus */
|
|
148
|
+
readonly behaviors?: readonly RuntimeBehavior[];
|
|
149
|
+
/**
|
|
150
|
+
* Intercept a `navigate` action before the default `window.location.assign`
|
|
151
|
+
* fallback runs. Return `true` to signal the host handled it (e.g. swapped
|
|
152
|
+
* to a sibling page in place, connected-preview style) — the default hard
|
|
153
|
+
* navigation is skipped. Return `false`/`undefined` to fall through to the
|
|
154
|
+
* default behavior.
|
|
155
|
+
*/
|
|
156
|
+
readonly onNavigateAction?: (url: string) => boolean;
|
|
157
|
+
/**
|
|
158
|
+
* What to render while the initial `fetchAllSources` pass is in flight.
|
|
159
|
+
*
|
|
160
|
+
* - `'gate'` (default) — the historical behavior: an all-or-nothing
|
|
161
|
+
* "Loading data..." placeholder replaces the ENTIRE block tree until the
|
|
162
|
+
* first fetch settles. Kept as the default so existing consumers (e.g.
|
|
163
|
+
* published `/s/` pages) are byte-identical.
|
|
164
|
+
* - `'immediate'` — render the block tree right away; expressions bound to
|
|
165
|
+
* still-loading sources resolve to `undefined` (never a literal `{{…}}`
|
|
166
|
+
* string — path expressions always evaluate successfully) and fill in as
|
|
167
|
+
* each source lands. Static chrome (navbar, headings, footer) is visible
|
|
168
|
+
* from the first frame. Pair with the `__loading.<sourceId>` /
|
|
169
|
+
* `__anyLoading` expression keys to drive per-widget skeletons.
|
|
170
|
+
*/
|
|
171
|
+
readonly loadingStrategy?: 'gate' | 'immediate';
|
|
172
|
+
/**
|
|
173
|
+
* Yesterday's rows while today's load. A source whose key (see
|
|
174
|
+
* `dataSourceCacheKey`) is present is seeded from the cache on the first
|
|
175
|
+
* frame and still re-fetched; the fresh result replaces the seed and is
|
|
176
|
+
* written back. Pairs naturally with `loadingStrategy: 'immediate'`.
|
|
177
|
+
*/
|
|
178
|
+
readonly dataCache?: SurfaceDataCache;
|
|
179
|
+
/**
|
|
180
|
+
* Configuration for the DataService this renderer creates.
|
|
181
|
+
*
|
|
182
|
+
* IT WAS NEVER PASSED. `<DataCapabilityProvider>` was mounted bare, so the
|
|
183
|
+
* service was built with no config — which means `getAccessToken` was always
|
|
184
|
+
* undefined and every `authProviderRef` on every rest source resolved to
|
|
185
|
+
* nobody. The field parsed, travelled and was read by a resolver that could
|
|
186
|
+
* not exist. Threading it is the repair; it is also what lets a host say
|
|
187
|
+
* which origin is its own, so our API can be called with a cookie and
|
|
188
|
+
* nobody else's can.
|
|
189
|
+
*/
|
|
190
|
+
readonly dataServiceConfig?: DataServiceConfig;
|
|
191
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data Binding Types for Surface Renderer
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for data-bound surface rendering.
|
|
5
|
+
* These types define the shape of surface JSON definitions that include
|
|
6
|
+
* dataSources, state, and expression-based prop bindings.
|
|
7
|
+
*
|
|
8
|
+
* @module @pwfabric/runtime/render/data-binding-types
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=data-binding-types.js.map
|