@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,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface Renderer Types
|
|
3
|
+
*
|
|
4
|
+
* Phase 2A.1: Type definitions for Surface-to-React rendering
|
|
5
|
+
*
|
|
6
|
+
* @module @pwfabric/runtime/render/types
|
|
7
|
+
*/
|
|
8
|
+
import type { Block, BreakpointName, SurfaceDocument, SurfaceTheme } from '@pwfabric/contracts';
|
|
9
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
10
|
+
import type { ImageAdapter as ImageAdapterType } from '../adapters/types.js';
|
|
11
|
+
import type { EntityFacade } from '../entity/facade.js';
|
|
12
|
+
import type { SurfaceConnectionsValue } from '../connectors/types.js';
|
|
13
|
+
export type { EntityFacade } from '../entity/facade.js';
|
|
14
|
+
export type { ImageAdapter, ImageAdapterProps } from '../adapters/types.js';
|
|
15
|
+
type ImageAdapter = ImageAdapterType;
|
|
16
|
+
/**
|
|
17
|
+
* Capability types that can be required by surfaces
|
|
18
|
+
* (defined capabilities)
|
|
19
|
+
*/
|
|
20
|
+
export type CapabilityType = 'auth' | 'data' | 'state' | 'navigation' | 'analytics' | 'seo' | 'i18n' | 'forms';
|
|
21
|
+
/**
|
|
22
|
+
* Renderable surface interface
|
|
23
|
+
*
|
|
24
|
+
* A structural projection of SurfaceDocument containing only the fields
|
|
25
|
+
* needed for rendering. Any object with the matching shape can be rendered,
|
|
26
|
+
* including custom definitions.
|
|
27
|
+
*
|
|
28
|
+
* Derived from SurfaceDocument so it stays structurally aligned with the
|
|
29
|
+
* canonical type.
|
|
30
|
+
*/
|
|
31
|
+
export type RenderableSurface = Pick<SurfaceDocument, 'blocks' | 'appearance' | 'capabilities'> & {
|
|
32
|
+
/** Optional surface identifier — used by `BehaviorSurfaceProvider` to scope the event bus */
|
|
33
|
+
readonly id?: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Props passed to block components
|
|
37
|
+
*/
|
|
38
|
+
export interface BlockComponentProps<T = Record<string, unknown>> {
|
|
39
|
+
/** Block definition */
|
|
40
|
+
readonly block: Block;
|
|
41
|
+
/** Resolved props (validated and defaulted) */
|
|
42
|
+
readonly props: T;
|
|
43
|
+
/** Rendered children (for container blocks) */
|
|
44
|
+
readonly children?: ReactNode;
|
|
45
|
+
/** Block context for capability access */
|
|
46
|
+
readonly context: BlockContext;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Block component type
|
|
50
|
+
*/
|
|
51
|
+
export type BlockComponent<T = Record<string, unknown>> = ((props: BlockComponentProps<T>) => ReactNode) & {
|
|
52
|
+
/**
|
|
53
|
+
* How the block wants to be sized when it sits in a flex ROW.
|
|
54
|
+
*
|
|
55
|
+
* The engine's default for a row child is an equal share (`flex: 1 1 0`) —
|
|
56
|
+
* right for two content columns, wrong for an avatar, a badge, a button: an
|
|
57
|
+
* intrinsic thing stretched to half a row is the single most measured layout
|
|
58
|
+
* defect of the 2026-09 surface audit (127 hand-written `flex: 0 0 auto`
|
|
59
|
+
* overrides across 14 receipts). A block whose natural width is its content
|
|
60
|
+
* declares `sizing: 'intrinsic'` — as a static on the component, the same
|
|
61
|
+
* way `displayName` travels — and the engine gives it `flex: 0 0 auto`.
|
|
62
|
+
* An authored flex hint on the instance still wins. The engine memorises no
|
|
63
|
+
* block names: the block declares, the engine obeys.
|
|
64
|
+
*/
|
|
65
|
+
sizing?: BlockSizing;
|
|
66
|
+
};
|
|
67
|
+
/** The only sizing word the engine knows besides its default (fluid share). */
|
|
68
|
+
export type BlockSizing = 'intrinsic';
|
|
69
|
+
/**
|
|
70
|
+
* Block component registry
|
|
71
|
+
*/
|
|
72
|
+
export type BlockComponentRegistry = Record<string, BlockComponent>;
|
|
73
|
+
/**
|
|
74
|
+
* Capability provider interface
|
|
75
|
+
*/
|
|
76
|
+
export interface CapabilityProvider {
|
|
77
|
+
/** Capability type */
|
|
78
|
+
readonly type: CapabilityType;
|
|
79
|
+
/** Provider-specific data */
|
|
80
|
+
readonly data?: unknown;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Block rendering context
|
|
84
|
+
*/
|
|
85
|
+
export interface BlockContext {
|
|
86
|
+
/** Available capabilities */
|
|
87
|
+
readonly capabilities: Map<CapabilityType, CapabilityProvider>;
|
|
88
|
+
/** Base path for routing */
|
|
89
|
+
readonly basePath: string;
|
|
90
|
+
/** Event handler */
|
|
91
|
+
readonly onEvent: ((event: SurfaceEvent) => void) | undefined;
|
|
92
|
+
/** Image adapter for framework-specific optimization */
|
|
93
|
+
readonly imageAdapter: ImageAdapter | undefined;
|
|
94
|
+
/** Current viewport breakpoint for responsive rendering */
|
|
95
|
+
readonly viewport?: BreakpointName;
|
|
96
|
+
/**
|
|
97
|
+
* Interaction mode (ADR render-unification). `onEvent` is a pure notification
|
|
98
|
+
* and always fires; `interactionMode` gates real SIDE-EFFECTS. Blocks that
|
|
99
|
+
* perform real navigation or data writes (e.g. `window.location.href`) MUST
|
|
100
|
+
* skip those when `interactionMode === 'inert'` so editor/preview renders
|
|
101
|
+
* don't trigger navigation or external mutations. Defaults to `live`.
|
|
102
|
+
*/
|
|
103
|
+
readonly interactionMode?: BlockInteractionMode;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Surface event types
|
|
107
|
+
*/
|
|
108
|
+
export type SurfaceEventType = 'click' | 'submit' | 'change' | 'navigate' | 'custom';
|
|
109
|
+
/**
|
|
110
|
+
* Surface event
|
|
111
|
+
*/
|
|
112
|
+
export interface SurfaceEvent {
|
|
113
|
+
/** Event type */
|
|
114
|
+
readonly type: SurfaceEventType;
|
|
115
|
+
/** Block ID that triggered the event */
|
|
116
|
+
readonly blockId: string;
|
|
117
|
+
/** Event payload */
|
|
118
|
+
readonly payload?: unknown;
|
|
119
|
+
/** Original DOM event (if applicable) */
|
|
120
|
+
readonly originalEvent?: Event;
|
|
121
|
+
/** Canonical bus event name (e.g. 'block:click', 'form:submit') — set by the renderer bridge */
|
|
122
|
+
readonly canonicalType?: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Surface renderer props
|
|
126
|
+
*/
|
|
127
|
+
/**
|
|
128
|
+
* Interaction mode for the runtime render (ADR render-unification).
|
|
129
|
+
* - `live` (default): full runtime behavior — data-source auto-refresh timers run
|
|
130
|
+
* and block-dispatched surface actions/events fire.
|
|
131
|
+
* - `inert`: editor/preview render — no auto-refresh timers, block-dispatched
|
|
132
|
+
* surface actions are no-ops, so an editor can intercept clicks (e.g. for
|
|
133
|
+
* selection) without the surface mutating its own state.
|
|
134
|
+
*/
|
|
135
|
+
export type BlockInteractionMode = 'live' | 'inert';
|
|
136
|
+
/**
|
|
137
|
+
* Props the runtime puts on each block's outermost wrapper element. The exact
|
|
138
|
+
* shape `renderBlock` would spread onto its own `<div>`. An editor decorator
|
|
139
|
+
* (see `renderBlockWrapper`) spreads these onto its own element so the runtime's
|
|
140
|
+
* computed layout + the per-block selector survive — the decorator never
|
|
141
|
+
* recomputes layout.
|
|
142
|
+
*/
|
|
143
|
+
export interface BlockWrapperProps {
|
|
144
|
+
readonly style?: CSSProperties;
|
|
145
|
+
/**
|
|
146
|
+
* The block id as a DOM id, so `#<blockId>` is a reachable anchor.
|
|
147
|
+
*
|
|
148
|
+
* Separate from `data-block-id`, which addresses blocks for styling and
|
|
149
|
+
* editing: only a real `id` makes a fragment link scroll, so without it
|
|
150
|
+
* same-page navigation would be silently impossible.
|
|
151
|
+
*
|
|
152
|
+
* A decorator that renders its own wrapper receives this and is expected to
|
|
153
|
+
* apply it — two elements carrying one id is worse than none.
|
|
154
|
+
*/
|
|
155
|
+
readonly id?: string;
|
|
156
|
+
/** Unified per-block selector — present on every render path. */
|
|
157
|
+
readonly 'data-block-id': string;
|
|
158
|
+
/** Any other `data-*` attributes the runtime sets (e.g. data-dynamic-block). */
|
|
159
|
+
readonly [dataAttr: `data-${string}`]: string | undefined;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Arguments passed to a `renderBlockWrapper` decorator. `children` is the
|
|
163
|
+
* runtime-rendered block content (already wrapped in its error boundary);
|
|
164
|
+
* `wrapperProps` carries the runtime-computed layout style + selectors.
|
|
165
|
+
*/
|
|
166
|
+
export interface BlockWrapperRenderArgs {
|
|
167
|
+
readonly block: Block;
|
|
168
|
+
readonly children: ReactNode;
|
|
169
|
+
readonly wrapperProps: BlockWrapperProps;
|
|
170
|
+
readonly parentBlock?: Block;
|
|
171
|
+
}
|
|
172
|
+
export interface SurfaceRendererProps {
|
|
173
|
+
/** Surface definition (starter or custom) */
|
|
174
|
+
readonly surface: RenderableSurface;
|
|
175
|
+
/** Capability providers */
|
|
176
|
+
readonly capabilities?: CapabilityProvider[];
|
|
177
|
+
/**
|
|
178
|
+
* App-level color scheme hint (kept for external API compat, not injected into BlockContext).
|
|
179
|
+
* Surface visual theming is done via surface.theme.
|
|
180
|
+
*/
|
|
181
|
+
readonly theme?: 'light' | 'dark';
|
|
182
|
+
/**
|
|
183
|
+
* the Project's shared theme tokens,
|
|
184
|
+
* merged as a layer BETWEEN the platform defaults and this surface's own
|
|
185
|
+
* `appearance.config.theme` — a surface that hasn't set a given token
|
|
186
|
+
* inherits the project's; one that has, keeps winning. Only wired for the
|
|
187
|
+
* in-process fallback resolution path (no tenant-installed ui-appearance
|
|
188
|
+
* atom bundle active); published/public rendering does not consume this
|
|
189
|
+
* yet — editor-only for now.
|
|
190
|
+
*/
|
|
191
|
+
readonly projectTheme?: SurfaceTheme;
|
|
192
|
+
/**
|
|
193
|
+
* The Project's dark OVERRIDES (`appearanceConfig.darkTheme`), as the authoring studio writes
|
|
194
|
+
* them: only the tokens the author changed. They sit on top of the dark
|
|
195
|
+
* variant DERIVED from the effective light theme, under this surface's own
|
|
196
|
+
* `appearance.config.darkTheme`. Omit it and the dark mode is the derivation
|
|
197
|
+
* plus the surface's overrides, as before.
|
|
198
|
+
*/
|
|
199
|
+
readonly projectDarkTheme?: SurfaceTheme;
|
|
200
|
+
/** Base path for links/routing */
|
|
201
|
+
readonly basePath?: string;
|
|
202
|
+
/** Event handler */
|
|
203
|
+
readonly onEvent?: (event: SurfaceEvent) => void;
|
|
204
|
+
/** Custom block component overrides */
|
|
205
|
+
readonly components?: Partial<BlockComponentRegistry>;
|
|
206
|
+
/** Wrapper className */
|
|
207
|
+
readonly className?: string;
|
|
208
|
+
/** Explicit viewport override (if not set, uses auto-detection) */
|
|
209
|
+
readonly viewport?: BreakpointName;
|
|
210
|
+
/** Grid gap between blocks in pixels (default: 16) */
|
|
211
|
+
readonly gap?: number | undefined;
|
|
212
|
+
/** Surface inner padding in pixels (default: 24) */
|
|
213
|
+
readonly padding?: number | undefined;
|
|
214
|
+
/**
|
|
215
|
+
* Image adapter for framework-specific image optimization
|
|
216
|
+
*
|
|
217
|
+
* Allows using Next.js Image, Astro Image, etc. while keeping
|
|
218
|
+
* surface definitions framework-agnostic.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```tsx
|
|
222
|
+
* import { NextImageAdapter } from '@pwfabric/runtime/adapters'
|
|
223
|
+
*
|
|
224
|
+
* <SurfaceRenderer
|
|
225
|
+
* surface={mySurface}
|
|
226
|
+
* imageAdapter={NextImageAdapter}
|
|
227
|
+
* />
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
readonly imageAdapter?: ImageAdapter;
|
|
231
|
+
/**
|
|
232
|
+
* EntityFacade instance for data model access.
|
|
233
|
+
* When provided, entity data sources and form bindings are activated.
|
|
234
|
+
* platform/entities is Tier 1 always-on — this prop is optional only
|
|
235
|
+
* because caller controls instantiation (ConnectorRegistry binding is app-specific).
|
|
236
|
+
*/
|
|
237
|
+
readonly entityFacade?: EntityFacade;
|
|
238
|
+
/**
|
|
239
|
+
* The surface's connections context — the world's
|
|
240
|
+
* configured connections (single dialect with the runner's
|
|
241
|
+
* `connections.json` entries) plus the loaded connector-engine registry.
|
|
242
|
+
* When provided, `{kind:'entity', connector}` data sources route through
|
|
243
|
+
* the registry and the value is exposed to blocks via
|
|
244
|
+
* `SurfaceConnectionsContext`. Absent = today's behavior (additive).
|
|
245
|
+
*/
|
|
246
|
+
readonly connections?: SurfaceConnectionsValue;
|
|
247
|
+
/**
|
|
248
|
+
* Editor-only seam (ADR render-unification): wrap each block's layout wrapper
|
|
249
|
+
* with custom chrome (selection/drag/hover). Receives the runtime-computed
|
|
250
|
+
* `wrapperProps` so the decorator never recomputes layout. When omitted
|
|
251
|
+
* (runtime/published path), each block renders in the default `<div>` —
|
|
252
|
+
* byte-identical to before this seam existed.
|
|
253
|
+
*/
|
|
254
|
+
readonly renderBlockWrapper?: (args: BlockWrapperRenderArgs) => ReactNode;
|
|
255
|
+
/**
|
|
256
|
+
* Interaction mode. Defaults to `live`. `inert` suppresses data auto-refresh
|
|
257
|
+
* and block-dispatched surface actions (for editor/preview embedding).
|
|
258
|
+
*/
|
|
259
|
+
readonly interactionMode?: BlockInteractionMode;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Block renderer props (internal)
|
|
263
|
+
*/
|
|
264
|
+
export interface BlockRendererProps {
|
|
265
|
+
/** Block to render */
|
|
266
|
+
readonly block: Block;
|
|
267
|
+
/** Rendering context */
|
|
268
|
+
readonly context: BlockContext;
|
|
269
|
+
/** Component registry */
|
|
270
|
+
readonly components: BlockComponentRegistry;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Render result with metadata
|
|
274
|
+
*/
|
|
275
|
+
export interface RenderResult {
|
|
276
|
+
/** Rendered element */
|
|
277
|
+
readonly element: ReactNode;
|
|
278
|
+
/** Block IDs in render tree */
|
|
279
|
+
readonly blockIds: string[];
|
|
280
|
+
/** Required capabilities */
|
|
281
|
+
readonly requiredCapabilities: CapabilityType[];
|
|
282
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/render/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Surface Renderer Types\n *\n * Phase 2A.1: Type definitions for Surface-to-React rendering\n *\n * @module @pwfabric/runtime/render/types\n */\n\nimport type { Block, BreakpointName, SurfaceDocument, SurfaceTheme } from '@pwfabric/contracts'\nimport type { CSSProperties, ReactNode } from 'react'\nimport type { ImageAdapter as ImageAdapterType } from '../adapters/types.js'\nimport type { EntityFacade } from '../entity/facade.js'\nimport type { SurfaceConnectionsValue } from '../connectors/types.js'\n\n// Re-export EntityFacade for consumers who import from @pwfabric/runtime/render\nexport type { EntityFacade } from '../entity/facade.js'\n\n// Re-export ImageAdapter type for consumers\nexport type { ImageAdapter, ImageAdapterProps } from '../adapters/types.js'\n\n// Local alias for use in this file\ntype ImageAdapter = ImageAdapterType\n\n// ============================================================\n// CAPABILITY TYPES (mirrored from starters to avoid circular dep)\n// ============================================================\n\n/**\n * Capability types that can be required by surfaces\n * (defined capabilities)\n */\nexport type CapabilityType =\n | 'auth'\n | 'data'\n | 'state'\n | 'navigation'\n | 'analytics'\n | 'seo'\n | 'i18n'\n | 'forms'\n\n// ============================================================\n// RENDERABLE SURFACE\n// ============================================================\n\n/**\n * Renderable surface interface\n *\n * A structural projection of SurfaceDocument containing only the fields\n * needed for rendering. Any object with the matching shape can be rendered,\n * including custom definitions.\n *\n * Derived from SurfaceDocument so it stays structurally aligned with the\n * canonical type.\n */\n// theme + layout + styleVariables collapsed into `appearance` ref;\n// dataSources + initialState moved into platform/persistence capability config.\nexport type RenderableSurface = Pick<SurfaceDocument, 'blocks' | 'appearance' | 'capabilities'> & {\n /** Optional surface identifier — used by `BehaviorSurfaceProvider` to scope the event bus */\n readonly id?: string\n}\n\n// ============================================================\n// BLOCK COMPONENT TYPES\n// ============================================================\n\n/**\n * Props passed to block components\n */\nexport interface BlockComponentProps<T = Record<string, unknown>> {\n /** Block definition */\n readonly block: Block\n /** Resolved props (validated and defaulted) */\n readonly props: T\n /** Rendered children (for container blocks) */\n readonly children?: ReactNode\n /** Block context for capability access */\n readonly context: BlockContext\n}\n\n/**\n * Block component type\n */\nexport type BlockComponent<T = Record<string, unknown>> = ((\n props: BlockComponentProps<T>\n) => ReactNode) & {\n /**\n * How the block wants to be sized when it sits in a flex ROW.\n *\n * The engine's default for a row child is an equal share (`flex: 1 1 0`) —\n * right for two content columns, wrong for an avatar, a badge, a button: an\n * intrinsic thing stretched to half a row is the single most measured layout\n * defect of the 2026-09 surface audit (127 hand-written `flex: 0 0 auto`\n * overrides across 14 receipts). A block whose natural width is its content\n * declares `sizing: 'intrinsic'` — as a static on the component, the same\n * way `displayName` travels — and the engine gives it `flex: 0 0 auto`.\n * An authored flex hint on the instance still wins. The engine memorises no\n * block names: the block declares, the engine obeys.\n */\n sizing?: BlockSizing\n}\n\n/** The only sizing word the engine knows besides its default (fluid share). */\nexport type BlockSizing = 'intrinsic'\n\n/**\n * Block component registry\n */\nexport type BlockComponentRegistry = Record<string, BlockComponent>\n\n// ============================================================\n// CAPABILITY CONTEXT\n// ============================================================\n\n/**\n * Capability provider interface\n */\nexport interface CapabilityProvider {\n /** Capability type */\n readonly type: CapabilityType\n /** Provider-specific data */\n readonly data?: unknown\n}\n\n/**\n * Block rendering context\n */\nexport interface BlockContext {\n /** Available capabilities */\n readonly capabilities: Map<CapabilityType, CapabilityProvider>\n /** Base path for routing */\n readonly basePath: string\n /** Event handler */\n readonly onEvent: ((event: SurfaceEvent) => void) | undefined\n /** Image adapter for framework-specific optimization */\n readonly imageAdapter: ImageAdapter | undefined\n /** Current viewport breakpoint for responsive rendering */\n readonly viewport?: BreakpointName\n /**\n * Interaction mode (ADR render-unification). `onEvent` is a pure notification\n * and always fires; `interactionMode` gates real SIDE-EFFECTS. Blocks that\n * perform real navigation or data writes (e.g. `window.location.href`) MUST\n * skip those when `interactionMode === 'inert'` so editor/preview renders\n * don't trigger navigation or external mutations. Defaults to `live`.\n */\n readonly interactionMode?: BlockInteractionMode\n}\n\n// ============================================================\n// SURFACE EVENTS\n// ============================================================\n\n/**\n * Surface event types\n */\nexport type SurfaceEventType = 'click' | 'submit' | 'change' | 'navigate' | 'custom'\n\n/**\n * Surface event\n */\nexport interface SurfaceEvent {\n /** Event type */\n readonly type: SurfaceEventType\n /** Block ID that triggered the event */\n readonly blockId: string\n /** Event payload */\n readonly payload?: unknown\n /** Original DOM event (if applicable) */\n readonly originalEvent?: Event\n /** Canonical bus event name (e.g. 'block:click', 'form:submit') — set by the renderer bridge */\n readonly canonicalType?: string\n}\n\n// ============================================================\n// RENDERER PROPS\n// ============================================================\n\n/**\n * Surface renderer props\n */\n/**\n * Interaction mode for the runtime render (ADR render-unification).\n * - `live` (default): full runtime behavior — data-source auto-refresh timers run\n * and block-dispatched surface actions/events fire.\n * - `inert`: editor/preview render — no auto-refresh timers, block-dispatched\n * surface actions are no-ops, so an editor can intercept clicks (e.g. for\n * selection) without the surface mutating its own state.\n */\nexport type BlockInteractionMode = 'live' | 'inert'\n\n/**\n * Props the runtime puts on each block's outermost wrapper element. The exact\n * shape `renderBlock` would spread onto its own `<div>`. An editor decorator\n * (see `renderBlockWrapper`) spreads these onto its own element so the runtime's\n * computed layout + the per-block selector survive — the decorator never\n * recomputes layout.\n */\nexport interface BlockWrapperProps {\n readonly style?: CSSProperties\n /**\n * The block id as a DOM id, so `#<blockId>` is a reachable anchor.\n *\n * Separate from `data-block-id`, which addresses blocks for styling and\n * editing: only a real `id` makes a fragment link scroll, so without it\n * same-page navigation would be silently impossible.\n *\n * A decorator that renders its own wrapper receives this and is expected to\n * apply it — two elements carrying one id is worse than none.\n */\n readonly id?: string\n /** Unified per-block selector — present on every render path. */\n readonly 'data-block-id': string\n /** Any other `data-*` attributes the runtime sets (e.g. data-dynamic-block). */\n readonly [dataAttr: `data-${string}`]: string | undefined\n}\n\n/**\n * Arguments passed to a `renderBlockWrapper` decorator. `children` is the\n * runtime-rendered block content (already wrapped in its error boundary);\n * `wrapperProps` carries the runtime-computed layout style + selectors.\n */\nexport interface BlockWrapperRenderArgs {\n readonly block: Block\n readonly children: ReactNode\n readonly wrapperProps: BlockWrapperProps\n readonly parentBlock?: Block\n}\n\nexport interface SurfaceRendererProps {\n /** Surface definition (starter or custom) */\n readonly surface: RenderableSurface\n /** Capability providers */\n readonly capabilities?: CapabilityProvider[]\n /**\n * App-level color scheme hint (kept for external API compat, not injected into BlockContext).\n * Surface visual theming is done via surface.theme.\n */\n readonly theme?: 'light' | 'dark'\n /**\n * the Project's shared theme tokens,\n * merged as a layer BETWEEN the platform defaults and this surface's own\n * `appearance.config.theme` — a surface that hasn't set a given token\n * inherits the project's; one that has, keeps winning. Only wired for the\n * in-process fallback resolution path (no tenant-installed ui-appearance\n * atom bundle active); published/public rendering does not consume this\n * yet — editor-only for now.\n */\n readonly projectTheme?: SurfaceTheme\n /**\n * The Project's dark OVERRIDES (`appearanceConfig.darkTheme`), as the authoring studio writes\n * them: only the tokens the author changed. They sit on top of the dark\n * variant DERIVED from the effective light theme, under this surface's own\n * `appearance.config.darkTheme`. Omit it and the dark mode is the derivation\n * plus the surface's overrides, as before.\n */\n readonly projectDarkTheme?: SurfaceTheme\n /** Base path for links/routing */\n readonly basePath?: string\n /** Event handler */\n readonly onEvent?: (event: SurfaceEvent) => void\n /** Custom block component overrides */\n readonly components?: Partial<BlockComponentRegistry>\n /** Wrapper className */\n readonly className?: string\n /** Explicit viewport override (if not set, uses auto-detection) */\n readonly viewport?: BreakpointName\n /** Grid gap between blocks in pixels (default: 16) */\n readonly gap?: number | undefined\n /** Surface inner padding in pixels (default: 24) */\n readonly padding?: number | undefined\n /**\n * Image adapter for framework-specific image optimization\n *\n * Allows using Next.js Image, Astro Image, etc. while keeping\n * surface definitions framework-agnostic.\n *\n * @example\n * ```tsx\n * import { NextImageAdapter } from '@pwfabric/runtime/adapters'\n *\n * <SurfaceRenderer\n * surface={mySurface}\n * imageAdapter={NextImageAdapter}\n * />\n * ```\n */\n readonly imageAdapter?: ImageAdapter\n /**\n * EntityFacade instance for data model access.\n * When provided, entity data sources and form bindings are activated.\n * platform/entities is Tier 1 always-on — this prop is optional only\n * because caller controls instantiation (ConnectorRegistry binding is app-specific).\n */\n readonly entityFacade?: EntityFacade\n /**\n * The surface's connections context — the world's\n * configured connections (single dialect with the runner's\n * `connections.json` entries) plus the loaded connector-engine registry.\n * When provided, `{kind:'entity', connector}` data sources route through\n * the registry and the value is exposed to blocks via\n * `SurfaceConnectionsContext`. Absent = today's behavior (additive).\n */\n readonly connections?: SurfaceConnectionsValue\n /**\n * Editor-only seam (ADR render-unification): wrap each block's layout wrapper\n * with custom chrome (selection/drag/hover). Receives the runtime-computed\n * `wrapperProps` so the decorator never recomputes layout. When omitted\n * (runtime/published path), each block renders in the default `<div>` —\n * byte-identical to before this seam existed.\n */\n readonly renderBlockWrapper?: (args: BlockWrapperRenderArgs) => ReactNode\n /**\n * Interaction mode. Defaults to `live`. `inert` suppresses data auto-refresh\n * and block-dispatched surface actions (for editor/preview embedding).\n */\n readonly interactionMode?: BlockInteractionMode\n}\n\n/**\n * Block renderer props (internal)\n */\nexport interface BlockRendererProps {\n /** Block to render */\n readonly block: Block\n /** Rendering context */\n readonly context: BlockContext\n /** Component registry */\n readonly components: BlockComponentRegistry\n}\n\n// ============================================================\n// RENDER RESULT\n// ============================================================\n\n/**\n * Render result with metadata\n */\nexport interface RenderResult {\n /** Rendered element */\n readonly element: ReactNode\n /** Block IDs in render tree */\n readonly blockIds: string[]\n /** Required capabilities */\n readonly requiredCapabilities: CapabilityType[]\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-breakpoint visibility CSS generation (the `hidden md:flex` equivalent).
|
|
3
|
+
*
|
|
4
|
+
* `block.layout.hideOn` / `block.layout.showOn` declare at which breakpoints a
|
|
5
|
+
* block is hidden / the only breakpoints where it is visible. Inline styles
|
|
6
|
+
* can't express media queries, so the runtime emits scoped CSS rules — keyed
|
|
7
|
+
* by the block's `data-block-id` — into the surface's generated `<style>`
|
|
8
|
+
* (alongside the box-sizing reset). The pixel thresholds are the SAME
|
|
9
|
+
* `BREAKPOINTS[].minWidth` values the span system uses.
|
|
10
|
+
*
|
|
11
|
+
* Semantics:
|
|
12
|
+
* - `hideOn: ['xs','sm']` → hidden across the xs+sm ranges → hidden below the
|
|
13
|
+
* md threshold (768px) → `@media (max-width:767.98px){ display:none }`.
|
|
14
|
+
* - `showOn: ['lg','xl']` → visible ONLY in the lg+xl ranges → hidden below
|
|
15
|
+
* lg (1024px) AND at/above the breakpoint after xl (2xl = 1536px).
|
|
16
|
+
* - `showOn` is the inverse of `hideOn`; when both are present `showOn` wins.
|
|
17
|
+
*
|
|
18
|
+
* @module @pwfabric/runtime/render/visibility-css
|
|
19
|
+
*/
|
|
20
|
+
import type { Block } from '@pwfabric/core';
|
|
21
|
+
import type { BreakpointName } from '@pwfabric/core';
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the SET of breakpoints at which a block must be hidden, given its
|
|
24
|
+
* `hideOn` / `showOn` declarations. `showOn` takes precedence (the block is
|
|
25
|
+
* hidden at every breakpoint NOT listed in `showOn`).
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveHiddenBreakpoints(hideOn: readonly BreakpointName[] | undefined, showOn: readonly BreakpointName[] | undefined): BreakpointName[];
|
|
28
|
+
/**
|
|
29
|
+
* Emit the CSS rule(s) that hide a single block at the resolved breakpoints.
|
|
30
|
+
* Targets `[data-block-id="<id>"]` scoped under the surface root so it cannot
|
|
31
|
+
* leak to the host page. Uses `!important` so the rule beats the inline layout
|
|
32
|
+
* style (`display:grid`/flex on the wrapper) it must override.
|
|
33
|
+
*
|
|
34
|
+
* Returns '' when there is nothing to hide.
|
|
35
|
+
*/
|
|
36
|
+
export declare function blockVisibilityCss(blockId: string, hidden: BreakpointName[], surfaceId?: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Walk a surface block tree and concatenate the per-block visibility CSS for
|
|
39
|
+
* every block declaring `hideOn` / `showOn`. Blocks without either are skipped
|
|
40
|
+
* (zero bytes emitted) so existing surfaces are byte-identical.
|
|
41
|
+
*/
|
|
42
|
+
export declare function collectVisibilityCss(blocks: readonly Block[], surfaceId?: string): string;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-breakpoint visibility CSS generation (the `hidden md:flex` equivalent).
|
|
3
|
+
*
|
|
4
|
+
* `block.layout.hideOn` / `block.layout.showOn` declare at which breakpoints a
|
|
5
|
+
* block is hidden / the only breakpoints where it is visible. Inline styles
|
|
6
|
+
* can't express media queries, so the runtime emits scoped CSS rules — keyed
|
|
7
|
+
* by the block's `data-block-id` — into the surface's generated `<style>`
|
|
8
|
+
* (alongside the box-sizing reset). The pixel thresholds are the SAME
|
|
9
|
+
* `BREAKPOINTS[].minWidth` values the span system uses.
|
|
10
|
+
*
|
|
11
|
+
* Semantics:
|
|
12
|
+
* - `hideOn: ['xs','sm']` → hidden across the xs+sm ranges → hidden below the
|
|
13
|
+
* md threshold (768px) → `@media (max-width:767.98px){ display:none }`.
|
|
14
|
+
* - `showOn: ['lg','xl']` → visible ONLY in the lg+xl ranges → hidden below
|
|
15
|
+
* lg (1024px) AND at/above the breakpoint after xl (2xl = 1536px).
|
|
16
|
+
* - `showOn` is the inverse of `hideOn`; when both are present `showOn` wins.
|
|
17
|
+
*
|
|
18
|
+
* @module @pwfabric/runtime/render/visibility-css
|
|
19
|
+
*/
|
|
20
|
+
import { BREAKPOINTS, BREAKPOINT_ORDER } from '@pwfabric/core';
|
|
21
|
+
import { blockSelector, collectScopedCss } from './scoped-css.js';
|
|
22
|
+
/** Sub-pixel epsilon so `max-width` ranges don't overlap the next `min-width`. */
|
|
23
|
+
const MAX_EPSILON = 0.02;
|
|
24
|
+
/** `[minWidth, maxExclusive)` pixel range a named breakpoint covers. */
|
|
25
|
+
function rangeFor(bp) {
|
|
26
|
+
const idx = BREAKPOINTS.findIndex((b) => b.name === bp);
|
|
27
|
+
const def = BREAKPOINTS[idx];
|
|
28
|
+
const next = BREAKPOINTS[idx + 1];
|
|
29
|
+
return {
|
|
30
|
+
min: def?.minWidth ?? 0,
|
|
31
|
+
maxExclusive: next?.minWidth ?? Number.POSITIVE_INFINITY,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolve the SET of breakpoints at which a block must be hidden, given its
|
|
36
|
+
* `hideOn` / `showOn` declarations. `showOn` takes precedence (the block is
|
|
37
|
+
* hidden at every breakpoint NOT listed in `showOn`).
|
|
38
|
+
*/
|
|
39
|
+
export function resolveHiddenBreakpoints(hideOn, showOn) {
|
|
40
|
+
if (showOn && showOn.length > 0) {
|
|
41
|
+
const visible = new Set(showOn);
|
|
42
|
+
return BREAKPOINT_ORDER.filter((bp) => !visible.has(bp));
|
|
43
|
+
}
|
|
44
|
+
if (hideOn && hideOn.length > 0) {
|
|
45
|
+
const hide = new Set(hideOn);
|
|
46
|
+
return BREAKPOINT_ORDER.filter((bp) => hide.has(bp));
|
|
47
|
+
}
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Collapse a set of hidden breakpoints into the minimal set of
|
|
52
|
+
* `[min, maxExclusive)` pixel ranges (contiguous breakpoints merge).
|
|
53
|
+
*/
|
|
54
|
+
function collapseRanges(hidden) {
|
|
55
|
+
// Order by the canonical breakpoint order so contiguity is by ascending width.
|
|
56
|
+
const ordered = BREAKPOINT_ORDER.filter((bp) => hidden.includes(bp));
|
|
57
|
+
const out = [];
|
|
58
|
+
for (const bp of ordered) {
|
|
59
|
+
const r = rangeFor(bp);
|
|
60
|
+
const last = out[out.length - 1];
|
|
61
|
+
if (last && last.maxExclusive === r.min) {
|
|
62
|
+
last.maxExclusive = r.maxExclusive; // contiguous → extend
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
out.push({ ...r });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
/** Build a single `@media` condition for a `[min, maxExclusive)` range. */
|
|
71
|
+
function mediaCondition(min, maxExclusive) {
|
|
72
|
+
const parts = [];
|
|
73
|
+
if (min > 0)
|
|
74
|
+
parts.push(`(min-width:${min}px)`);
|
|
75
|
+
if (Number.isFinite(maxExclusive))
|
|
76
|
+
parts.push(`(max-width:${maxExclusive - MAX_EPSILON}px)`);
|
|
77
|
+
return parts.join(' and ');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Emit the CSS rule(s) that hide a single block at the resolved breakpoints.
|
|
81
|
+
* Targets `[data-block-id="<id>"]` scoped under the surface root so it cannot
|
|
82
|
+
* leak to the host page. Uses `!important` so the rule beats the inline layout
|
|
83
|
+
* style (`display:grid`/flex on the wrapper) it must override.
|
|
84
|
+
*
|
|
85
|
+
* Returns '' when there is nothing to hide.
|
|
86
|
+
*/
|
|
87
|
+
export function blockVisibilityCss(blockId, hidden, surfaceId) {
|
|
88
|
+
if (hidden.length === 0)
|
|
89
|
+
return '';
|
|
90
|
+
const ranges = collapseRanges(hidden);
|
|
91
|
+
// The whole spectrum is hidden (no showOn match anywhere): unconditional hide.
|
|
92
|
+
const everything = ranges.length === 1 && ranges[0].min === 0 && !Number.isFinite(ranges[0].maxExclusive);
|
|
93
|
+
const selector = blockSelector(blockId, surfaceId);
|
|
94
|
+
if (everything) {
|
|
95
|
+
return `${selector}{display:none !important}`;
|
|
96
|
+
}
|
|
97
|
+
return ranges
|
|
98
|
+
.map((r) => {
|
|
99
|
+
const cond = mediaCondition(r.min, r.maxExclusive);
|
|
100
|
+
return `@media ${cond}{${selector}{display:none !important}}`;
|
|
101
|
+
})
|
|
102
|
+
.join('');
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Walk a surface block tree and concatenate the per-block visibility CSS for
|
|
106
|
+
* every block declaring `hideOn` / `showOn`. Blocks without either are skipped
|
|
107
|
+
* (zero bytes emitted) so existing surfaces are byte-identical.
|
|
108
|
+
*/
|
|
109
|
+
export function collectVisibilityCss(blocks, surfaceId) {
|
|
110
|
+
return collectScopedCss(blocks, (block) => {
|
|
111
|
+
const layout = block.layout;
|
|
112
|
+
if (layout && (layout.hideOn?.length || layout.showOn?.length)) {
|
|
113
|
+
const hidden = resolveHiddenBreakpoints(layout.hideOn, layout.showOn);
|
|
114
|
+
return blockVisibilityCss(block.id, hidden, surfaceId);
|
|
115
|
+
}
|
|
116
|
+
return '';
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=visibility-css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visibility-css.js","sourceRoot":"","sources":["../../src/render/visibility-css.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Per-breakpoint visibility CSS generation (the `hidden md:flex` equivalent).\n *\n * `block.layout.hideOn` / `block.layout.showOn` declare at which breakpoints a\n * block is hidden / the only breakpoints where it is visible. Inline styles\n * can't express media queries, so the runtime emits scoped CSS rules — keyed\n * by the block's `data-block-id` — into the surface's generated `<style>`\n * (alongside the box-sizing reset). The pixel thresholds are the SAME\n * `BREAKPOINTS[].minWidth` values the span system uses.\n *\n * Semantics:\n * - `hideOn: ['xs','sm']` → hidden across the xs+sm ranges → hidden below the\n * md threshold (768px) → `@media (max-width:767.98px){ display:none }`.\n * - `showOn: ['lg','xl']` → visible ONLY in the lg+xl ranges → hidden below\n * lg (1024px) AND at/above the breakpoint after xl (2xl = 1536px).\n * - `showOn` is the inverse of `hideOn`; when both are present `showOn` wins.\n *\n * @module @pwfabric/runtime/render/visibility-css\n */\n\nimport type { Block } from '@pwfabric/core'\nimport { BREAKPOINTS, BREAKPOINT_ORDER } from '@pwfabric/core'\nimport type { BreakpointName } from '@pwfabric/core'\nimport { blockSelector, collectScopedCss } from './scoped-css.js'\n\n/** Sub-pixel epsilon so `max-width` ranges don't overlap the next `min-width`. */\nconst MAX_EPSILON = 0.02\n\n/** `[minWidth, maxExclusive)` pixel range a named breakpoint covers. */\nfunction rangeFor(bp: BreakpointName): { min: number; maxExclusive: number } {\n const idx = BREAKPOINTS.findIndex((b) => b.name === bp)\n const def = BREAKPOINTS[idx]\n const next = BREAKPOINTS[idx + 1]\n return {\n min: def?.minWidth ?? 0,\n maxExclusive: next?.minWidth ?? Number.POSITIVE_INFINITY,\n }\n}\n\n/**\n * Resolve the SET of breakpoints at which a block must be hidden, given its\n * `hideOn` / `showOn` declarations. `showOn` takes precedence (the block is\n * hidden at every breakpoint NOT listed in `showOn`).\n */\nexport function resolveHiddenBreakpoints(\n hideOn: readonly BreakpointName[] | undefined,\n showOn: readonly BreakpointName[] | undefined\n): BreakpointName[] {\n if (showOn && showOn.length > 0) {\n const visible = new Set(showOn)\n return BREAKPOINT_ORDER.filter((bp) => !visible.has(bp))\n }\n if (hideOn && hideOn.length > 0) {\n const hide = new Set(hideOn)\n return BREAKPOINT_ORDER.filter((bp) => hide.has(bp))\n }\n return []\n}\n\n/**\n * Collapse a set of hidden breakpoints into the minimal set of\n * `[min, maxExclusive)` pixel ranges (contiguous breakpoints merge).\n */\nfunction collapseRanges(hidden: BreakpointName[]): { min: number; maxExclusive: number }[] {\n // Order by the canonical breakpoint order so contiguity is by ascending width.\n const ordered = BREAKPOINT_ORDER.filter((bp) => hidden.includes(bp))\n const out: { min: number; maxExclusive: number }[] = []\n for (const bp of ordered) {\n const r = rangeFor(bp)\n const last = out[out.length - 1]\n if (last && last.maxExclusive === r.min) {\n last.maxExclusive = r.maxExclusive // contiguous → extend\n } else {\n out.push({ ...r })\n }\n }\n return out\n}\n\n/** Build a single `@media` condition for a `[min, maxExclusive)` range. */\nfunction mediaCondition(min: number, maxExclusive: number): string {\n const parts: string[] = []\n if (min > 0) parts.push(`(min-width:${min}px)`)\n if (Number.isFinite(maxExclusive)) parts.push(`(max-width:${maxExclusive - MAX_EPSILON}px)`)\n return parts.join(' and ')\n}\n\n/**\n * Emit the CSS rule(s) that hide a single block at the resolved breakpoints.\n * Targets `[data-block-id=\"<id>\"]` scoped under the surface root so it cannot\n * leak to the host page. Uses `!important` so the rule beats the inline layout\n * style (`display:grid`/flex on the wrapper) it must override.\n *\n * Returns '' when there is nothing to hide.\n */\nexport function blockVisibilityCss(\n blockId: string,\n hidden: BreakpointName[],\n surfaceId?: string\n): string {\n if (hidden.length === 0) return ''\n const ranges = collapseRanges(hidden)\n // The whole spectrum is hidden (no showOn match anywhere): unconditional hide.\n const everything = ranges.length === 1 && ranges[0]!.min === 0 && !Number.isFinite(ranges[0]!.maxExclusive)\n const selector = blockSelector(blockId, surfaceId)\n if (everything) {\n return `${selector}{display:none !important}`\n }\n return ranges\n .map((r) => {\n const cond = mediaCondition(r.min, r.maxExclusive)\n return `@media ${cond}{${selector}{display:none !important}}`\n })\n .join('')\n}\n\n/**\n * Walk a surface block tree and concatenate the per-block visibility CSS for\n * every block declaring `hideOn` / `showOn`. Blocks without either are skipped\n * (zero bytes emitted) so existing surfaces are byte-identical.\n */\nexport function collectVisibilityCss(blocks: readonly Block[], surfaceId?: string): string {\n return collectScopedCss(blocks, (block) => {\n const layout = block.layout as\n | { hideOn?: readonly BreakpointName[]; showOn?: readonly BreakpointName[] }\n | undefined\n if (layout && (layout.hideOn?.length || layout.showOn?.length)) {\n const hidden = resolveHiddenBreakpoints(layout.hideOn, layout.showOn)\n return blockVisibilityCss(block.id, hidden, surfaceId)\n }\n return ''\n })\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Width scope — splits blocks into groups while KEEPING SOURCE ORDER.
|
|
3
|
+
*
|
|
4
|
+
* WHY. If the surface root carried both the 12-column grid and
|
|
5
|
+
* `maxWidth: var(--pw-layout-container-max-width)` + `margin: 0 auto`,
|
|
6
|
+
* persistent chrome would sit inside the centred box too (on a 1536px screen
|
|
7
|
+
* a persistent rail would start 218px in from the edge). The rule: persistent
|
|
8
|
+
* navigation chrome belongs to the viewport, the content body to the measure.
|
|
9
|
+
*
|
|
10
|
+
* WHY GROUPS, NOT BUCKETS. A surface runs `[navbar][body…][bottombar]`.
|
|
11
|
+
* Collecting `viewport`-scoped blocks into one bucket and `container` ones
|
|
12
|
+
* into another would break the order and put the bottom bar next to the top
|
|
13
|
+
* bar. Consecutive grouping keeps the order: three groups, three DOM siblings.
|
|
14
|
+
*
|
|
15
|
+
* WHY NOT 100vw. The `width:100vw; margin-inline:calc(50% - 50vw)` trick is
|
|
16
|
+
* the short way out of a centred container and is NOT used: `100vw` counts
|
|
17
|
+
* the scrollbar too, so every page with a vertical scrollbar would get ~15px
|
|
18
|
+
* of horizontal overflow — the very defect this module exists to avoid.
|
|
19
|
+
*
|
|
20
|
+
* @module @pwfabric/runtime/render/width-scope
|
|
21
|
+
*/
|
|
22
|
+
import { type Block, type BreakpointName } from '@pwfabric/core';
|
|
23
|
+
import type { WidthScope } from '@pwfabric/contracts';
|
|
24
|
+
export interface WidthScopeChunk {
|
|
25
|
+
readonly scope: WidthScope;
|
|
26
|
+
readonly blocks: readonly Block[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A block's scope at this breakpoint. Without a declaration it is
|
|
30
|
+
* `container`, so a block that declares nothing keeps the default behaviour.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveWidthScope(block: Block, viewport: BreakpointName): WidthScope;
|
|
33
|
+
/** Groups consecutive blocks of the same scope together; order is kept. */
|
|
34
|
+
export declare function chunkByWidthScope(blocks: readonly Block[], viewport: BreakpointName): readonly WidthScopeChunk[];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Width scope — splits blocks into groups while KEEPING SOURCE ORDER.
|
|
3
|
+
*
|
|
4
|
+
* WHY. If the surface root carried both the 12-column grid and
|
|
5
|
+
* `maxWidth: var(--pw-layout-container-max-width)` + `margin: 0 auto`,
|
|
6
|
+
* persistent chrome would sit inside the centred box too (on a 1536px screen
|
|
7
|
+
* a persistent rail would start 218px in from the edge). The rule: persistent
|
|
8
|
+
* navigation chrome belongs to the viewport, the content body to the measure.
|
|
9
|
+
*
|
|
10
|
+
* WHY GROUPS, NOT BUCKETS. A surface runs `[navbar][body…][bottombar]`.
|
|
11
|
+
* Collecting `viewport`-scoped blocks into one bucket and `container` ones
|
|
12
|
+
* into another would break the order and put the bottom bar next to the top
|
|
13
|
+
* bar. Consecutive grouping keeps the order: three groups, three DOM siblings.
|
|
14
|
+
*
|
|
15
|
+
* WHY NOT 100vw. The `width:100vw; margin-inline:calc(50% - 50vw)` trick is
|
|
16
|
+
* the short way out of a centred container and is NOT used: `100vw` counts
|
|
17
|
+
* the scrollbar too, so every page with a vertical scrollbar would get ~15px
|
|
18
|
+
* of horizontal overflow — the very defect this module exists to avoid.
|
|
19
|
+
*
|
|
20
|
+
* @module @pwfabric/runtime/render/width-scope
|
|
21
|
+
*/
|
|
22
|
+
import { DEFAULT_BLOCK_LAYOUT, resolveResponsiveValue, } from '@pwfabric/core';
|
|
23
|
+
/**
|
|
24
|
+
* A block's scope at this breakpoint. Without a declaration it is
|
|
25
|
+
* `container`, so a block that declares nothing keeps the default behaviour.
|
|
26
|
+
*/
|
|
27
|
+
export function resolveWidthScope(block, viewport) {
|
|
28
|
+
const layout = block.layout ?? DEFAULT_BLOCK_LAYOUT;
|
|
29
|
+
return resolveResponsiveValue(layout.widthScope, viewport) ?? 'container';
|
|
30
|
+
}
|
|
31
|
+
/** Groups consecutive blocks of the same scope together; order is kept. */
|
|
32
|
+
export function chunkByWidthScope(blocks, viewport) {
|
|
33
|
+
const chunks = [];
|
|
34
|
+
for (const block of blocks) {
|
|
35
|
+
const scope = resolveWidthScope(block, viewport);
|
|
36
|
+
const last = chunks[chunks.length - 1];
|
|
37
|
+
if (last && last.scope === scope)
|
|
38
|
+
last.blocks.push(block);
|
|
39
|
+
else
|
|
40
|
+
chunks.push({ scope, blocks: [block] });
|
|
41
|
+
}
|
|
42
|
+
return chunks;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=width-scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"width-scope.js","sourceRoot":"","sources":["../../src/render/width-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GAGvB,MAAM,gBAAgB,CAAA;AAWvB;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAY,EAAE,QAAwB;IACtE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,oBAAoB,CAAA;IACnD,OAAO,sBAAsB,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,WAAW,CAAA;AAC3E,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB,CAC/B,MAAwB,EACxB,QAAwB;IAExB,MAAM,MAAM,GAA6C,EAAE,CAAA;IAC3D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QAChD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QACtC,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;;YACpD,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IAC9C,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["/**\n * Width scope — splits blocks into groups while KEEPING SOURCE ORDER.\n *\n * WHY. If the surface root carried both the 12-column grid and\n * `maxWidth: var(--pw-layout-container-max-width)` + `margin: 0 auto`,\n * persistent chrome would sit inside the centred box too (on a 1536px screen\n * a persistent rail would start 218px in from the edge). The rule: persistent\n * navigation chrome belongs to the viewport, the content body to the measure.\n *\n * WHY GROUPS, NOT BUCKETS. A surface runs `[navbar][body…][bottombar]`.\n * Collecting `viewport`-scoped blocks into one bucket and `container` ones\n * into another would break the order and put the bottom bar next to the top\n * bar. Consecutive grouping keeps the order: three groups, three DOM siblings.\n *\n * WHY NOT 100vw. The `width:100vw; margin-inline:calc(50% - 50vw)` trick is\n * the short way out of a centred container and is NOT used: `100vw` counts\n * the scrollbar too, so every page with a vertical scrollbar would get ~15px\n * of horizontal overflow — the very defect this module exists to avoid.\n *\n * @module @pwfabric/runtime/render/width-scope\n */\nimport {\n DEFAULT_BLOCK_LAYOUT,\n resolveResponsiveValue,\n type Block,\n type BreakpointName,\n} from '@pwfabric/core'\n// `WidthScope` comes from CONTRACTS, not from core's parallel copy:\n// `block.layout` is typed by contracts, and the two definitions are kept in\n// sync by hand, so the contracts type is the one to follow.\nimport type { WidthScope } from '@pwfabric/contracts'\n\nexport interface WidthScopeChunk {\n readonly scope: WidthScope\n readonly blocks: readonly Block[]\n}\n\n/**\n * A block's scope at this breakpoint. Without a declaration it is\n * `container`, so a block that declares nothing keeps the default behaviour.\n */\nexport function resolveWidthScope(block: Block, viewport: BreakpointName): WidthScope {\n const layout = block.layout ?? DEFAULT_BLOCK_LAYOUT\n return resolveResponsiveValue(layout.widthScope, viewport) ?? 'container'\n}\n\n/** Groups consecutive blocks of the same scope together; order is kept. */\nexport function chunkByWidthScope(\n blocks: readonly Block[],\n viewport: BreakpointName\n): readonly WidthScopeChunk[] {\n const chunks: { scope: WidthScope; blocks: Block[] }[] = []\n for (const block of blocks) {\n const scope = resolveWidthScope(block, viewport)\n const last = chunks[chunks.length - 1]\n if (last && last.scope === scope) last.blocks.push(block)\n else chunks.push({ scope, blocks: [block] })\n }\n return chunks\n}\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WRITE-ONLY SOURCES — a form's target that nothing on the page reads.
|
|
3
|
+
*
|
|
4
|
+
* A data source a form writes to (`platform/entities` `config.formBindings[].sourceId`)
|
|
5
|
+
* was also fetched as a list on mount and again after every submit (the
|
|
6
|
+
* bridge's `refreshAll`). For an intake-only model — anonymous visitors may
|
|
7
|
+
* create, never list — that is a refused request on every visit and every
|
|
8
|
+
* submit (`GET /_host/records/<model>` → 403
|
|
9
|
+
* `RECORDS_NOT_PUBLIC`, `__errors.records` set, no block bound to it).
|
|
10
|
+
*
|
|
11
|
+
* A source is write-only when:
|
|
12
|
+
* - at least one form binding targets it, and every binding that does writes
|
|
13
|
+
* with POST (a PATCH/PUT needs the loaded record to know what to update), and
|
|
14
|
+
* - its id is referenced NOWHERE else: no block (props, expressions, actions,
|
|
15
|
+
* repeat), no behavior, no other source, no other capability config.
|
|
16
|
+
*
|
|
17
|
+
* The reference check is a whole-word search of every string, which errs on
|
|
18
|
+
* the side of fetching: a stray word equal to the id keeps today's behaviour.
|
|
19
|
+
* A write-only source stays declared and registered — it is still the write
|
|
20
|
+
* target — it is just never asked for its rows.
|
|
21
|
+
*
|
|
22
|
+
* @module @pwfabric/runtime/render/write-only-sources
|
|
23
|
+
*/
|
|
24
|
+
export interface WriteOnlySourceInput {
|
|
25
|
+
readonly blocks: readonly unknown[];
|
|
26
|
+
readonly dataSources: readonly {
|
|
27
|
+
readonly id: string;
|
|
28
|
+
}[];
|
|
29
|
+
readonly capabilities?: readonly unknown[] | undefined;
|
|
30
|
+
readonly behaviors?: readonly unknown[] | undefined;
|
|
31
|
+
}
|
|
32
|
+
/** The ids of the declared sources that are only ever written to. */
|
|
33
|
+
export declare function writeOnlySourceIds(input: WriteOnlySourceInput): ReadonlySet<string>;
|