@a2ui/web_core 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.tsbuildinfo +1 -0
- package/LICENSE +203 -0
- package/README.md +50 -4
- package/package.json +42 -72
- package/{dist/src → src}/v0_8/data/guards.js +13 -13
- package/src/v0_8/data/guards.test.d.ts +2 -0
- package/src/v0_8/data/guards.test.d.ts.map +1 -0
- package/src/v0_8/data/guards.test.js +174 -0
- package/src/v0_8/data/guards.test.js.map +1 -0
- package/{dist/src → src}/v0_8/data/model-processor.d.ts +1 -1
- package/{dist/src → src}/v0_8/data/model-processor.d.ts.map +1 -1
- package/{dist/src → src}/v0_8/data/model-processor.js +51 -40
- package/src/v0_8/data/model-processor.js.map +1 -0
- package/src/v0_8/data/model-processor.test.d.ts +2 -0
- package/src/v0_8/data/model-processor.test.d.ts.map +1 -0
- package/src/v0_8/data/model-processor.test.js +712 -0
- package/src/v0_8/data/model-processor.test.js.map +1 -0
- package/src/v0_8/errors.d.ts +35 -0
- package/src/v0_8/errors.d.ts.map +1 -0
- package/src/v0_8/errors.js +65 -0
- package/src/v0_8/errors.js.map +1 -0
- package/src/v0_8/events/validation-event.d.ts.map +1 -0
- package/{dist/src → src}/v0_8/events/validation-event.js.map +1 -1
- package/{dist/src → src}/v0_8/index.d.ts +35 -4
- package/{dist/src → src}/v0_8/index.d.ts.map +1 -1
- package/src/v0_8/index.js +28 -0
- package/src/v0_8/index.js.map +1 -0
- package/src/v0_8/schema/common-types.d.ts +1189 -0
- package/src/v0_8/schema/common-types.d.ts.map +1 -0
- package/src/v0_8/schema/common-types.js +381 -0
- package/src/v0_8/schema/common-types.js.map +1 -0
- package/src/v0_8/schema/server-to-client.d.ts +17949 -0
- package/src/v0_8/schema/server-to-client.d.ts.map +1 -0
- package/src/v0_8/schema/server-to-client.js +228 -0
- package/src/v0_8/schema/server-to-client.js.map +1 -0
- package/src/v0_8/schema/verify-schema.test.d.ts +17 -0
- package/src/v0_8/schema/verify-schema.test.d.ts.map +1 -0
- package/src/v0_8/schema/verify-schema.test.js +167 -0
- package/src/v0_8/schema/verify-schema.test.js.map +1 -0
- package/{dist/src → src}/v0_8/schemas/server_to_client.json +1 -1
- package/src/v0_8/schemas/server_to_client_with_standard_catalog.json +817 -787
- package/{dist/src → src}/v0_8/schemas/standard_catalog_definition.json +26 -0
- package/{dist/src → src}/v0_8/styles/behavior.js +13 -13
- package/{dist/src → src}/v0_8/styles/border.js +13 -13
- package/{dist/src → src}/v0_8/styles/colors.js +13 -13
- package/{dist/src → src}/v0_8/styles/colors.js.map +1 -1
- package/src/v0_8/styles/icons.d.ts +11 -0
- package/{dist/src → src}/v0_8/styles/icons.d.ts.map +1 -1
- package/{dist/src → src}/v0_8/styles/icons.js +17 -14
- package/{dist/src → src}/v0_8/styles/icons.js.map +1 -1
- package/src/v0_8/styles/index.js +35 -0
- package/{dist/src → src}/v0_8/styles/layout.js +13 -13
- package/{dist/src → src}/v0_8/styles/layout.js.map +1 -1
- package/src/v0_8/styles/opacity.js +24 -0
- package/src/v0_8/{events/index.ts → styles/shared.js} +3 -4
- package/src/v0_8/styles/styles.test.d.ts +2 -0
- package/src/v0_8/styles/styles.test.d.ts.map +1 -0
- package/src/v0_8/styles/styles.test.js +86 -0
- package/src/v0_8/styles/styles.test.js.map +1 -0
- package/{dist/src → src}/v0_8/styles/type.js +13 -13
- package/{dist/src → src}/v0_8/styles/utils.js +13 -13
- package/{dist/src → src}/v0_8/types/client-event.d.ts +10 -8
- package/src/v0_8/types/client-event.d.ts.map +1 -0
- package/src/v0_8/types/client-event.js +17 -0
- package/src/v0_8/types/colors.js +19 -0
- package/src/v0_8/types/components.d.ts +41 -0
- package/src/v0_8/types/components.d.ts.map +1 -0
- package/src/v0_8/types/components.js +17 -0
- package/src/v0_8/types/primitives.d.ts +9 -0
- package/src/v0_8/types/primitives.d.ts.map +1 -0
- package/src/v0_8/types/primitives.js +17 -0
- package/{dist/src → src}/v0_8/types/types.d.ts +44 -22
- package/src/v0_8/types/types.d.ts.map +1 -0
- package/src/v0_8/types/types.js +17 -0
- package/src/v0_9/basic_catalog/components/basic_components.d.ts +3359 -0
- package/src/v0_9/basic_catalog/components/basic_components.d.ts.map +1 -0
- package/src/v0_9/basic_catalog/components/basic_components.js +448 -0
- package/src/v0_9/basic_catalog/components/basic_components.js.map +1 -0
- package/src/v0_9/basic_catalog/components/basic_components.test.d.ts +2 -0
- package/src/v0_9/basic_catalog/components/basic_components.test.d.ts.map +1 -0
- package/src/v0_9/basic_catalog/components/basic_components.test.js +46 -0
- package/src/v0_9/basic_catalog/components/basic_components.test.js.map +1 -0
- package/src/v0_9/basic_catalog/expressions/expression_parser.d.ts +38 -0
- package/src/v0_9/basic_catalog/expressions/expression_parser.d.ts.map +1 -0
- package/src/v0_9/basic_catalog/expressions/expression_parser.js +294 -0
- package/src/v0_9/basic_catalog/expressions/expression_parser.js.map +1 -0
- package/src/v0_9/basic_catalog/expressions/expression_parser.test.d.ts +2 -0
- package/src/v0_9/basic_catalog/expressions/expression_parser.test.d.ts.map +1 -0
- package/src/v0_9/basic_catalog/expressions/expression_parser.test.js +126 -0
- package/src/v0_9/basic_catalog/expressions/expression_parser.test.js.map +1 -0
- package/src/v0_9/basic_catalog/functions/basic_functions.d.ts +32 -0
- package/src/v0_9/basic_catalog/functions/basic_functions.d.ts.map +1 -0
- package/src/v0_9/basic_catalog/functions/basic_functions.js +212 -0
- package/src/v0_9/basic_catalog/functions/basic_functions.js.map +1 -0
- package/src/v0_9/basic_catalog/functions/basic_functions.test.d.ts +2 -0
- package/src/v0_9/basic_catalog/functions/basic_functions.test.d.ts.map +1 -0
- package/src/v0_9/basic_catalog/functions/basic_functions.test.js +301 -0
- package/src/v0_9/basic_catalog/functions/basic_functions.test.js.map +1 -0
- package/src/v0_9/basic_catalog/functions/basic_functions_api.d.ts +930 -0
- package/src/v0_9/basic_catalog/functions/basic_functions_api.d.ts.map +1 -0
- package/src/v0_9/basic_catalog/functions/basic_functions_api.js +466 -0
- package/src/v0_9/basic_catalog/functions/basic_functions_api.js.map +1 -0
- package/src/v0_9/basic_catalog/index.d.ts +5 -0
- package/src/v0_9/basic_catalog/index.d.ts.map +1 -0
- package/src/v0_9/basic_catalog/index.js +20 -0
- package/src/v0_9/basic_catalog/index.js.map +1 -0
- package/src/v0_9/catalog/function_invoker.d.ts +12 -0
- package/src/v0_9/catalog/function_invoker.d.ts.map +1 -0
- package/src/v0_9/catalog/function_invoker.js +17 -0
- package/src/v0_9/catalog/function_invoker.js.map +1 -0
- package/src/v0_9/catalog/types.d.ts +80 -0
- package/src/v0_9/catalog/types.d.ts.map +1 -0
- package/src/v0_9/catalog/types.js +68 -0
- package/src/v0_9/catalog/types.js.map +1 -0
- package/src/v0_9/catalog/types.test.d.ts +2 -0
- package/src/v0_9/catalog/types.test.d.ts.map +1 -0
- package/src/v0_9/catalog/types.test.js +88 -0
- package/src/v0_9/catalog/types.test.js.map +1 -0
- package/src/v0_9/common/events.d.ts +45 -0
- package/src/v0_9/common/events.d.ts.map +1 -0
- package/src/v0_9/common/events.js +58 -0
- package/src/v0_9/common/events.js.map +1 -0
- package/src/v0_9/common/events.test.d.ts +2 -0
- package/src/v0_9/common/events.test.d.ts.map +1 -0
- package/src/v0_9/common/events.test.js +58 -0
- package/src/v0_9/common/events.test.js.map +1 -0
- package/src/v0_9/errors.d.ts +40 -0
- package/src/v0_9/errors.d.ts.map +1 -0
- package/src/v0_9/errors.js +69 -0
- package/src/v0_9/errors.js.map +1 -0
- package/src/v0_9/index.d.ts +152 -0
- package/src/v0_9/index.d.ts.map +1 -0
- package/src/v0_9/index.js +41 -0
- package/src/v0_9/index.js.map +1 -0
- package/src/v0_9/processing/message-processor.d.ts +70 -0
- package/src/v0_9/processing/message-processor.d.ts.map +1 -0
- package/src/v0_9/processing/message-processor.js +289 -0
- package/src/v0_9/processing/message-processor.js.map +1 -0
- package/src/v0_9/processing/message-processor.test.js +547 -0
- package/src/v0_9/processing/message-processor.test.js.map +1 -0
- package/src/v0_9/reactivity/signals.d.ts +43 -0
- package/src/v0_9/reactivity/signals.d.ts.map +1 -0
- package/src/v0_9/reactivity/signals.js +17 -0
- package/src/v0_9/reactivity/signals.js.map +1 -0
- package/src/v0_9/reactivity/signals.test.d.ts +17 -0
- package/src/v0_9/reactivity/signals.test.d.ts.map +1 -0
- package/src/v0_9/reactivity/signals.test.js +100 -0
- package/src/v0_9/reactivity/signals.test.js.map +1 -0
- package/src/v0_9/rendering/component-context.d.ts +35 -0
- package/src/v0_9/rendering/component-context.d.ts.map +1 -0
- package/src/v0_9/rendering/component-context.js +49 -0
- package/src/v0_9/rendering/component-context.js.map +1 -0
- package/src/v0_9/rendering/component-context.test.d.ts +2 -0
- package/src/v0_9/rendering/component-context.test.d.ts.map +1 -0
- package/src/v0_9/rendering/component-context.test.js +55 -0
- package/src/v0_9/rendering/component-context.test.js.map +1 -0
- package/src/v0_9/rendering/data-context.d.ts +99 -0
- package/src/v0_9/rendering/data-context.d.ts.map +1 -0
- package/src/v0_9/rendering/data-context.js +310 -0
- package/src/v0_9/rendering/data-context.js.map +1 -0
- package/src/v0_9/rendering/data-context.test.js +379 -0
- package/src/v0_9/rendering/data-context.test.js.map +1 -0
- package/src/v0_9/rendering/generic-binder.d.ts +122 -0
- package/src/v0_9/rendering/generic-binder.d.ts.map +1 -0
- package/src/v0_9/rendering/generic-binder.js +315 -0
- package/src/v0_9/rendering/generic-binder.js.map +1 -0
- package/src/v0_9/rendering/generic-binder.test.d.ts +2 -0
- package/src/v0_9/rendering/generic-binder.test.d.ts.map +1 -0
- package/src/v0_9/rendering/generic-binder.test.js +166 -0
- package/src/v0_9/rendering/generic-binder.test.js.map +1 -0
- package/src/v0_9/schema/client-capabilities.d.ts +34 -0
- package/src/v0_9/schema/client-capabilities.d.ts.map +1 -0
- package/src/v0_9/schema/client-capabilities.js +17 -0
- package/src/v0_9/schema/client-capabilities.js.map +1 -0
- package/src/v0_9/schema/client-to-server.d.ts +208 -0
- package/src/v0_9/schema/client-to-server.d.ts.map +1 -0
- package/src/v0_9/schema/client-to-server.js +104 -0
- package/src/v0_9/schema/client-to-server.js.map +1 -0
- package/src/v0_9/schema/client-to-server.test.d.ts +2 -0
- package/src/v0_9/schema/client-to-server.test.d.ts.map +1 -0
- package/src/v0_9/schema/client-to-server.test.js +85 -0
- package/src/v0_9/schema/client-to-server.test.js.map +1 -0
- package/{dist/src → src}/v0_9/schema/common-types.d.ts +318 -88
- package/src/v0_9/schema/common-types.d.ts.map +1 -0
- package/src/v0_9/schema/common-types.js +141 -0
- package/src/v0_9/schema/common-types.js.map +1 -0
- package/src/v0_9/schema/index.d.ts +5 -0
- package/src/v0_9/schema/index.d.ts.map +1 -0
- package/src/v0_9/schema/index.js +20 -0
- package/src/v0_9/schema/index.js.map +1 -0
- package/src/v0_9/schema/server-to-client.d.ts +307 -0
- package/src/v0_9/schema/server-to-client.d.ts.map +1 -0
- package/src/v0_9/schema/server-to-client.js +92 -0
- package/src/v0_9/schema/server-to-client.js.map +1 -0
- package/src/v0_9/schema/verify-schema.test.d.ts +17 -0
- package/src/v0_9/schema/verify-schema.test.d.ts.map +1 -0
- package/src/v0_9/schema/verify-schema.test.js +174 -0
- package/src/v0_9/schema/verify-schema.test.js.map +1 -0
- package/src/v0_9/schemas/basic_catalog.json +1387 -0
- package/src/v0_9/schemas/client_capabilities.json +97 -0
- package/src/v0_9/schemas/client_data_model.json +22 -0
- package/src/v0_9/schemas/client_to_server.json +104 -0
- package/src/v0_9/schemas/client_to_server_list.json +10 -0
- package/src/v0_9/schemas/common_types.json +315 -0
- package/src/v0_9/schemas/sample.json +22 -0
- package/src/v0_9/schemas/server_capabilities.json +26 -0
- package/src/v0_9/schemas/server_to_client.json +131 -0
- package/src/v0_9/schemas/server_to_client_list.json +10 -0
- package/src/v0_9/state/component-model.d.ts +36 -0
- package/src/v0_9/state/component-model.d.ts.map +1 -0
- package/src/v0_9/state/component-model.js +65 -0
- package/src/v0_9/state/component-model.js.map +1 -0
- package/{dist/src → src}/v0_9/state/component-model.test.js +23 -0
- package/src/v0_9/state/component-model.test.js.map +1 -0
- package/src/v0_9/state/data-model.d.ts +75 -0
- package/src/v0_9/state/data-model.d.ts.map +1 -0
- package/src/v0_9/state/data-model.js +235 -0
- package/src/v0_9/state/data-model.js.map +1 -0
- package/{dist/src → src}/v0_9/state/data-model.test.js +77 -17
- package/src/v0_9/state/data-model.test.js.map +1 -0
- package/src/v0_9/state/surface-components-model.d.ts +45 -0
- package/src/v0_9/state/surface-components-model.d.ts.map +1 -0
- package/src/v0_9/state/surface-components-model.js +86 -0
- package/src/v0_9/state/surface-components-model.js.map +1 -0
- package/{dist/src → src}/v0_9/state/surface-components-model.test.js +44 -2
- package/src/v0_9/state/surface-components-model.test.js.map +1 -0
- package/{dist/src → src}/v0_9/state/surface-group-model.d.ts +28 -1
- package/src/v0_9/state/surface-group-model.d.ts.map +1 -0
- package/{dist/src → src}/v0_9/state/surface-group-model.js +44 -1
- package/src/v0_9/state/surface-group-model.js.map +1 -0
- package/{dist/src → src}/v0_9/state/surface-group-model.test.js +47 -6
- package/src/v0_9/state/surface-group-model.test.js.map +1 -0
- package/src/v0_9/state/surface-model.d.ts +62 -0
- package/src/v0_9/state/surface-model.d.ts.map +1 -0
- package/src/v0_9/state/surface-model.js +101 -0
- package/src/v0_9/state/surface-model.js.map +1 -0
- package/src/v0_9/state/surface-model.test.js +93 -0
- package/src/v0_9/state/surface-model.test.js.map +1 -0
- package/src/v0_9/test/function_execution.spec.d.ts +17 -0
- package/src/v0_9/test/function_execution.spec.d.ts.map +1 -0
- package/src/v0_9/test/function_execution.spec.js +127 -0
- package/src/v0_9/test/function_execution.spec.js.map +1 -0
- package/src/v0_9/test/test-utils.d.ts.map +1 -0
- package/{dist/src → src}/v0_9/test/test-utils.js +15 -0
- package/src/v0_9/test/test-utils.js.map +1 -0
- package/dist/.tsbuildinfo +0 -1
- package/dist/src/v0_8/data/model-processor.js.map +0 -1
- package/dist/src/v0_8/events/validation-event.d.ts.map +0 -1
- package/dist/src/v0_8/index.js +0 -12
- package/dist/src/v0_8/index.js.map +0 -1
- package/dist/src/v0_8/schemas/server_to_client_with_standard_catalog.json +0 -823
- package/dist/src/v0_8/styles/icons.d.ts +0 -11
- package/dist/src/v0_8/styles/index.js +0 -35
- package/dist/src/v0_8/styles/opacity.js +0 -24
- package/dist/src/v0_8/styles/shared.js +0 -17
- package/dist/src/v0_8/types/client-event.d.ts.map +0 -1
- package/dist/src/v0_8/types/client-event.js +0 -17
- package/dist/src/v0_8/types/colors.js +0 -19
- package/dist/src/v0_8/types/components.d.ts +0 -176
- package/dist/src/v0_8/types/components.d.ts.map +0 -1
- package/dist/src/v0_8/types/components.js +0 -17
- package/dist/src/v0_8/types/primitives.d.ts +0 -43
- package/dist/src/v0_8/types/primitives.d.ts.map +0 -1
- package/dist/src/v0_8/types/primitives.js +0 -17
- package/dist/src/v0_8/types/types.d.ts.map +0 -1
- package/dist/src/v0_8/types/types.js +0 -17
- package/dist/src/v0_9/catalog/types.d.ts +0 -27
- package/dist/src/v0_9/catalog/types.d.ts.map +0 -1
- package/dist/src/v0_9/catalog/types.js +0 -11
- package/dist/src/v0_9/catalog/types.js.map +0 -1
- package/dist/src/v0_9/common/events.d.ts +0 -24
- package/dist/src/v0_9/common/events.d.ts.map +0 -1
- package/dist/src/v0_9/common/events.js +0 -29
- package/dist/src/v0_9/common/events.js.map +0 -1
- package/dist/src/v0_9/index.d.ts +0 -11
- package/dist/src/v0_9/index.d.ts.map +0 -1
- package/dist/src/v0_9/index.js +0 -11
- package/dist/src/v0_9/index.js.map +0 -1
- package/dist/src/v0_9/processing/message-processor.d.ts +0 -34
- package/dist/src/v0_9/processing/message-processor.d.ts.map +0 -1
- package/dist/src/v0_9/processing/message-processor.js +0 -128
- package/dist/src/v0_9/processing/message-processor.js.map +0 -1
- package/dist/src/v0_9/processing/message-processor.test.js +0 -112
- package/dist/src/v0_9/processing/message-processor.test.js.map +0 -1
- package/dist/src/v0_9/rendering/component-context.d.ts +0 -17
- package/dist/src/v0_9/rendering/component-context.d.ts.map +0 -1
- package/dist/src/v0_9/rendering/component-context.js +0 -21
- package/dist/src/v0_9/rendering/component-context.js.map +0 -1
- package/dist/src/v0_9/rendering/data-context.d.ts +0 -37
- package/dist/src/v0_9/rendering/data-context.d.ts.map +0 -1
- package/dist/src/v0_9/rendering/data-context.js +0 -97
- package/dist/src/v0_9/rendering/data-context.js.map +0 -1
- package/dist/src/v0_9/rendering/data-context.test.js +0 -71
- package/dist/src/v0_9/rendering/data-context.test.js.map +0 -1
- package/dist/src/v0_9/schema/common-types.d.ts.map +0 -1
- package/dist/src/v0_9/schema/common-types.js +0 -92
- package/dist/src/v0_9/schema/common-types.js.map +0 -1
- package/dist/src/v0_9/schema/index.d.ts +0 -3
- package/dist/src/v0_9/schema/index.d.ts.map +0 -1
- package/dist/src/v0_9/schema/index.js +0 -3
- package/dist/src/v0_9/schema/index.js.map +0 -1
- package/dist/src/v0_9/schema/server-to-client.d.ts +0 -84
- package/dist/src/v0_9/schema/server-to-client.d.ts.map +0 -1
- package/dist/src/v0_9/schema/server-to-client.js +0 -21
- package/dist/src/v0_9/schema/server-to-client.js.map +0 -1
- package/dist/src/v0_9/state/component-model.d.ts +0 -16
- package/dist/src/v0_9/state/component-model.d.ts.map +0 -1
- package/dist/src/v0_9/state/component-model.js +0 -24
- package/dist/src/v0_9/state/component-model.js.map +0 -1
- package/dist/src/v0_9/state/component-model.test.js.map +0 -1
- package/dist/src/v0_9/state/data-model.d.ts +0 -47
- package/dist/src/v0_9/state/data-model.d.ts.map +0 -1
- package/dist/src/v0_9/state/data-model.js +0 -191
- package/dist/src/v0_9/state/data-model.js.map +0 -1
- package/dist/src/v0_9/state/data-model.test.js.map +0 -1
- package/dist/src/v0_9/state/surface-components-model.d.ts +0 -19
- package/dist/src/v0_9/state/surface-components-model.d.ts.map +0 -1
- package/dist/src/v0_9/state/surface-components-model.js +0 -42
- package/dist/src/v0_9/state/surface-components-model.js.map +0 -1
- package/dist/src/v0_9/state/surface-components-model.test.js.map +0 -1
- package/dist/src/v0_9/state/surface-group-model.d.ts.map +0 -1
- package/dist/src/v0_9/state/surface-group-model.js.map +0 -1
- package/dist/src/v0_9/state/surface-group-model.test.js.map +0 -1
- package/dist/src/v0_9/state/surface-model.d.ts +0 -23
- package/dist/src/v0_9/state/surface-model.d.ts.map +0 -1
- package/dist/src/v0_9/state/surface-model.js +0 -28
- package/dist/src/v0_9/state/surface-model.js.map +0 -1
- package/dist/src/v0_9/state/surface-model.test.js +0 -39
- package/dist/src/v0_9/state/surface-model.test.js.map +0 -1
- package/dist/src/v0_9/test/test-utils.d.ts.map +0 -1
- package/dist/src/v0_9/test/test-utils.js.map +0 -1
- package/src/v0_8/data/guards.ts +0 -236
- package/src/v0_8/data/model-processor.ts +0 -855
- package/src/v0_8/events/base.ts +0 -24
- package/src/v0_8/events/validation-event.ts +0 -66
- package/src/v0_8/index.ts +0 -12
- package/src/v0_8/styles/behavior.ts +0 -55
- package/src/v0_8/styles/border.ts +0 -42
- package/src/v0_8/styles/colors.ts +0 -100
- package/src/v0_8/styles/icons.ts +0 -60
- package/src/v0_8/styles/index.ts +0 -37
- package/src/v0_8/styles/layout.ts +0 -235
- package/src/v0_8/styles/opacity.ts +0 -24
- package/src/v0_8/styles/shared.ts +0 -17
- package/src/v0_8/styles/type.ts +0 -156
- package/src/v0_8/styles/utils.ts +0 -104
- package/src/v0_8/types/client-event.ts +0 -80
- package/src/v0_8/types/colors.ts +0 -66
- package/src/v0_8/types/components.ts +0 -213
- package/src/v0_8/types/primitives.ts +0 -60
- package/src/v0_8/types/types.ts +0 -557
- package/src/v0_9/catalog/types.ts +0 -38
- package/src/v0_9/common/events.ts +0 -44
- package/src/v0_9/index.ts +0 -12
- package/src/v0_9/processing/message-processor.test.ts +0 -133
- package/src/v0_9/processing/message-processor.ts +0 -150
- package/src/v0_9/rendering/component-context.ts +0 -36
- package/src/v0_9/rendering/data-context.test.ts +0 -85
- package/src/v0_9/rendering/data-context.ts +0 -110
- package/src/v0_9/schema/common-types.ts +0 -125
- package/src/v0_9/schema/index.ts +0 -2
- package/src/v0_9/schema/server-to-client.ts +0 -23
- package/src/v0_9/state/component-model.test.ts +0 -50
- package/src/v0_9/state/component-model.ts +0 -32
- package/src/v0_9/state/data-model.test.ts +0 -257
- package/src/v0_9/state/data-model.ts +0 -239
- package/src/v0_9/state/surface-components-model.test.ts +0 -59
- package/src/v0_9/state/surface-components-model.ts +0 -48
- package/src/v0_9/state/surface-group-model.test.ts +0 -82
- package/src/v0_9/state/surface-group-model.ts +0 -66
- package/src/v0_9/state/surface-model.test.ts +0 -44
- package/src/v0_9/state/surface-model.ts +0 -39
- package/src/v0_9/test/test-utils.ts +0 -22
- /package/{dist/src → src}/v0_8/data/guards.d.ts +0 -0
- /package/{dist/src → src}/v0_8/data/guards.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/data/guards.js.map +0 -0
- /package/{dist/src → src}/v0_8/events/base.d.ts +0 -0
- /package/{dist/src → src}/v0_8/events/base.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/events/base.js +0 -0
- /package/{dist/src → src}/v0_8/events/base.js.map +0 -0
- /package/{dist/src → src}/v0_8/events/index.d.ts +0 -0
- /package/{dist/src → src}/v0_8/events/index.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/events/index.js +0 -0
- /package/{dist/src → src}/v0_8/events/index.js.map +0 -0
- /package/{dist/src → src}/v0_8/events/validation-event.d.ts +0 -0
- /package/{dist/src → src}/v0_8/events/validation-event.js +0 -0
- /package/{dist/src → src}/v0_8/schemas/a2ui_client_capabilities_schema.json +0 -0
- /package/{dist/src → src}/v0_8/schemas/catalog_description_schema.json +0 -0
- /package/{dist/src → src}/v0_8/schemas/client_to_server.json +0 -0
- /package/{dist/src → src}/v0_8/styles/behavior.d.ts +0 -0
- /package/{dist/src → src}/v0_8/styles/behavior.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/styles/behavior.js.map +0 -0
- /package/{dist/src → src}/v0_8/styles/border.d.ts +0 -0
- /package/{dist/src → src}/v0_8/styles/border.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/styles/border.js.map +0 -0
- /package/{dist/src → src}/v0_8/styles/colors.d.ts +0 -0
- /package/{dist/src → src}/v0_8/styles/colors.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/styles/index.d.ts +0 -0
- /package/{dist/src → src}/v0_8/styles/index.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/styles/index.js.map +0 -0
- /package/{dist/src → src}/v0_8/styles/layout.d.ts +0 -0
- /package/{dist/src → src}/v0_8/styles/layout.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/styles/opacity.d.ts +0 -0
- /package/{dist/src → src}/v0_8/styles/opacity.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/styles/opacity.js.map +0 -0
- /package/{dist/src → src}/v0_8/styles/shared.d.ts +0 -0
- /package/{dist/src → src}/v0_8/styles/shared.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/styles/shared.js.map +0 -0
- /package/{dist/src → src}/v0_8/styles/type.d.ts +0 -0
- /package/{dist/src → src}/v0_8/styles/type.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/styles/type.js.map +0 -0
- /package/{dist/src → src}/v0_8/styles/utils.d.ts +0 -0
- /package/{dist/src → src}/v0_8/styles/utils.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/styles/utils.js.map +0 -0
- /package/{dist/src → src}/v0_8/types/client-event.js.map +0 -0
- /package/{dist/src → src}/v0_8/types/colors.d.ts +0 -0
- /package/{dist/src → src}/v0_8/types/colors.d.ts.map +0 -0
- /package/{dist/src → src}/v0_8/types/colors.js.map +0 -0
- /package/{dist/src → src}/v0_8/types/components.js.map +0 -0
- /package/{dist/src → src}/v0_8/types/primitives.js.map +0 -0
- /package/{dist/src → src}/v0_8/types/types.js.map +0 -0
- /package/{dist/src → src}/v0_9/processing/message-processor.test.d.ts +0 -0
- /package/{dist/src → src}/v0_9/processing/message-processor.test.d.ts.map +0 -0
- /package/{dist/src → src}/v0_9/rendering/data-context.test.d.ts +0 -0
- /package/{dist/src → src}/v0_9/rendering/data-context.test.d.ts.map +0 -0
- /package/{dist/src → src}/v0_9/state/component-model.test.d.ts +0 -0
- /package/{dist/src → src}/v0_9/state/component-model.test.d.ts.map +0 -0
- /package/{dist/src → src}/v0_9/state/data-model.test.d.ts +0 -0
- /package/{dist/src → src}/v0_9/state/data-model.test.d.ts.map +0 -0
- /package/{dist/src → src}/v0_9/state/surface-components-model.test.d.ts +0 -0
- /package/{dist/src → src}/v0_9/state/surface-components-model.test.d.ts.map +0 -0
- /package/{dist/src → src}/v0_9/state/surface-group-model.test.d.ts +0 -0
- /package/{dist/src → src}/v0_9/state/surface-group-model.test.d.ts.map +0 -0
- /package/{dist/src → src}/v0_9/state/surface-model.test.d.ts +0 -0
- /package/{dist/src → src}/v0_9/state/surface-model.test.d.ts.map +0 -0
- /package/{dist/src → src}/v0_9/test/test-utils.d.ts +0 -0
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
2
|
-
import { describe, it, beforeEach } from 'node:test';
|
|
3
|
-
import { ComponentModel } from './component-model.js';
|
|
4
|
-
|
|
5
|
-
describe('ComponentModel', () => {
|
|
6
|
-
let component: ComponentModel;
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
component = new ComponentModel('c1', 'Button', { label: 'Click Me' });
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('initializes properties', () => {
|
|
13
|
-
assert.strictEqual(component.id, 'c1');
|
|
14
|
-
assert.strictEqual(component.type, 'Button');
|
|
15
|
-
assert.strictEqual(component.properties.label, 'Click Me');
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('updates properties', () => {
|
|
19
|
-
component.properties = { label: 'Clicked' };
|
|
20
|
-
assert.strictEqual(component.properties.label, 'Clicked');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('notifies listeners on update', () => {
|
|
24
|
-
let updatedComponent: ComponentModel | undefined;
|
|
25
|
-
|
|
26
|
-
component.onUpdated.subscribe((c: ComponentModel) => {
|
|
27
|
-
updatedComponent = c;
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
component.properties = { label: 'New' };
|
|
31
|
-
|
|
32
|
-
assert.strictEqual(updatedComponent, component);
|
|
33
|
-
assert.strictEqual(updatedComponent?.properties.label, 'New');
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('unsubscribes listeners', () => {
|
|
37
|
-
let callCount = 0;
|
|
38
|
-
|
|
39
|
-
const sub = component.onUpdated.subscribe(() => {
|
|
40
|
-
callCount++;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
component.properties = { label: '1' };
|
|
44
|
-
assert.strictEqual(callCount, 1);
|
|
45
|
-
|
|
46
|
-
sub.unsubscribe();
|
|
47
|
-
component.properties = { label: '2' };
|
|
48
|
-
assert.strictEqual(callCount, 1);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { EventEmitter, EventSource } from '../common/events.js';
|
|
2
|
-
|
|
3
|
-
export class ComponentModel {
|
|
4
|
-
private _properties: Record<string, any>;
|
|
5
|
-
private readonly _onUpdated = new EventEmitter<ComponentModel>();
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Fires whenever the component's properties are updated.
|
|
9
|
-
*/
|
|
10
|
-
readonly onUpdated: EventSource<ComponentModel> = this._onUpdated;
|
|
11
|
-
|
|
12
|
-
constructor(
|
|
13
|
-
readonly id: string,
|
|
14
|
-
readonly type: string,
|
|
15
|
-
initialProperties: Record<string, any>
|
|
16
|
-
) {
|
|
17
|
-
this._properties = initialProperties;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get properties(): Record<string, any> {
|
|
21
|
-
return this._properties;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
set properties(newProperties: Record<string, any>) {
|
|
25
|
-
this._properties = newProperties;
|
|
26
|
-
this._onUpdated.emit(this);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
dispose(): void {
|
|
30
|
-
this._onUpdated.dispose();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
2
|
-
import { test, describe, it, beforeEach } from 'node:test';
|
|
3
|
-
import { DataModel } from './data-model.js';
|
|
4
|
-
|
|
5
|
-
describe('DataModel', () => {
|
|
6
|
-
let model: DataModel;
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
model = new DataModel({
|
|
10
|
-
user: {
|
|
11
|
-
name: 'Alice',
|
|
12
|
-
settings: {
|
|
13
|
-
theme: 'dark'
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
items: ['a', 'b', 'c']
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// --- Basic Retrieval ---
|
|
21
|
-
|
|
22
|
-
it('retrieves root data', () => {
|
|
23
|
-
assert.deepStrictEqual(model.get('/'), { user: { name: 'Alice', settings: { theme: 'dark' } }, items: ['a', 'b', 'c'] });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('retrieves nested path', () => {
|
|
27
|
-
assert.strictEqual(model.get('/user/name'), 'Alice');
|
|
28
|
-
assert.strictEqual(model.get('/user/settings/theme'), 'dark');
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('retrieves array items', () => {
|
|
32
|
-
assert.strictEqual(model.get('/items/0'), 'a');
|
|
33
|
-
assert.strictEqual(model.get('/items/1'), 'b');
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('returns undefined for non-existent paths', () => {
|
|
37
|
-
assert.strictEqual(model.get('/user/age'), undefined);
|
|
38
|
-
assert.strictEqual(model.get('/unknown/path'), undefined);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// --- Updates ---
|
|
42
|
-
|
|
43
|
-
it('sets value at existing path', () => {
|
|
44
|
-
model.set('/user/name', 'Bob');
|
|
45
|
-
assert.strictEqual(model.get('/user/name'), 'Bob');
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('sets value at new path', () => {
|
|
49
|
-
model.set('/user/age', 30);
|
|
50
|
-
assert.strictEqual(model.get('/user/age'), 30);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('creates intermediate objects', () => {
|
|
54
|
-
model.set('/a/b/c', 'foo');
|
|
55
|
-
assert.strictEqual(model.get('/a/b/c'), 'foo');
|
|
56
|
-
assert.notStrictEqual(model.get('/a/b'), undefined);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('removes keys when value is undefined', () => {
|
|
60
|
-
model.set('/user/name', undefined);
|
|
61
|
-
assert.strictEqual(model.get('/user/name'), undefined);
|
|
62
|
-
assert.strictEqual(Object.keys(model.get('/user')).includes('name'), false);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('replaces root object on root update', () => {
|
|
66
|
-
model.set('/', { newRoot: true });
|
|
67
|
-
assert.deepStrictEqual(model.get('/'), { newRoot: true });
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// --- Array / List Handling (Flutter Parity) ---
|
|
71
|
-
|
|
72
|
-
it('List: set and get', () => {
|
|
73
|
-
model.set('/list/0', 'hello');
|
|
74
|
-
assert.strictEqual(model.get('/list/0'), 'hello');
|
|
75
|
-
assert.ok(Array.isArray(model.get('/list')));
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('List: append and get', () => {
|
|
79
|
-
model.set('/list/0', 'hello');
|
|
80
|
-
model.set('/list/1', 'world');
|
|
81
|
-
assert.strictEqual(model.get('/list/0'), 'hello');
|
|
82
|
-
assert.strictEqual(model.get('/list/1'), 'world');
|
|
83
|
-
assert.strictEqual(model.get('/list').length, 2);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('List: update existing index', () => {
|
|
87
|
-
model.set('/items/1', 'updated');
|
|
88
|
-
assert.strictEqual(model.get('/items/1'), 'updated');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('Nested structures are created automatically', () => {
|
|
92
|
-
// Should create nested map and list: { a: { b: [ { c: 123 } ] } }
|
|
93
|
-
model.set('/a/b/0/c', 123);
|
|
94
|
-
assert.strictEqual(model.get('/a/b/0/c'), 123);
|
|
95
|
-
assert.ok(Array.isArray(model.get('/a/b')));
|
|
96
|
-
assert.ok(!Array.isArray(model.get('/a/b/0')));
|
|
97
|
-
|
|
98
|
-
// Should create nested maps
|
|
99
|
-
model.set('/x/y/z', 'hello');
|
|
100
|
-
assert.strictEqual(model.get('/x/y/z'), 'hello');
|
|
101
|
-
|
|
102
|
-
// Should create nested lists
|
|
103
|
-
model.set('/nestedList/0/0', 'inner');
|
|
104
|
-
assert.strictEqual(model.get('/nestedList/0/0'), 'inner');
|
|
105
|
-
assert.ok(Array.isArray(model.get('/nestedList')));
|
|
106
|
-
assert.ok(Array.isArray(model.get('/nestedList/0')));
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
// --- Subscriptions ---
|
|
110
|
-
|
|
111
|
-
it('returns a subscription object', () => {
|
|
112
|
-
model.set('/a', 1);
|
|
113
|
-
const sub = model.subscribe<number>('/a', (val) => updatedValue = val);
|
|
114
|
-
assert.strictEqual(sub.value, 1);
|
|
115
|
-
|
|
116
|
-
let updatedValue: number | undefined;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
model.set('/a', 2);
|
|
120
|
-
assert.strictEqual(sub.value, 2);
|
|
121
|
-
assert.strictEqual(updatedValue, 2);
|
|
122
|
-
|
|
123
|
-
sub.unsubscribe();
|
|
124
|
-
// Verify listener removed
|
|
125
|
-
model.set('/a', 3);
|
|
126
|
-
assert.strictEqual(updatedValue, 2);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('notifies subscribers on exact match', () => {
|
|
130
|
-
let called = false;
|
|
131
|
-
const sub = model.subscribe('/user/name', (val) => {
|
|
132
|
-
assert.strictEqual(val, 'Charlie');
|
|
133
|
-
called = true;
|
|
134
|
-
});
|
|
135
|
-
model.set('/user/name', 'Charlie');
|
|
136
|
-
assert.strictEqual(called, true, 'Callback was never called');
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('notifies ancestor subscribers (Container Semantics)', () => {
|
|
140
|
-
let called = false;
|
|
141
|
-
const sub = model.subscribe('/user', (val: any) => {
|
|
142
|
-
assert.strictEqual(val.name, 'Dave');
|
|
143
|
-
called = true;
|
|
144
|
-
});
|
|
145
|
-
model.set('/user/name', 'Dave');
|
|
146
|
-
assert.strictEqual(called, true, 'Callback was never called');
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('notifies descendant subscribers', () => {
|
|
150
|
-
let called = false;
|
|
151
|
-
const sub = model.subscribe('/user/settings/theme', (val) => {
|
|
152
|
-
assert.strictEqual(val, 'light');
|
|
153
|
-
called = true;
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// We update the parent object
|
|
157
|
-
model.set('/user/settings', { theme: 'light' });
|
|
158
|
-
assert.strictEqual(called, true, 'Callback was never called');
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('notifies root subscriber', () => {
|
|
162
|
-
let called = false;
|
|
163
|
-
const sub = model.subscribe('/', (val: any) => {
|
|
164
|
-
assert.strictEqual(val.newProp, 'test');
|
|
165
|
-
called = true;
|
|
166
|
-
});
|
|
167
|
-
model.set('/newProp', 'test');
|
|
168
|
-
assert.strictEqual(called, true, 'Callback was never called');
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('notifies parent when child updates', () => {
|
|
172
|
-
model.set('/parent', { child: 'initial' });
|
|
173
|
-
|
|
174
|
-
let parentValue: any;
|
|
175
|
-
const sub = model.subscribe('/parent', (val) => parentValue = val);
|
|
176
|
-
|
|
177
|
-
model.set('/parent/child', 'updated');
|
|
178
|
-
assert.deepStrictEqual(parentValue, { child: 'updated' });
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
it('stops notifying after dispose', () => {
|
|
182
|
-
let count = 0;
|
|
183
|
-
const sub = model.subscribe('/', () => count++);
|
|
184
|
-
|
|
185
|
-
model.dispose();
|
|
186
|
-
model.set('/foo', 'bar');
|
|
187
|
-
assert.strictEqual(count, 0);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it('supports multiple subscribers to the same path', () => {
|
|
191
|
-
let callCount1 = 0;
|
|
192
|
-
let callCount2 = 0;
|
|
193
|
-
|
|
194
|
-
const sub1 = model.subscribe('/user/name', () => callCount1++);
|
|
195
|
-
|
|
196
|
-
const sub2 = model.subscribe('/user/name', () => callCount2++);
|
|
197
|
-
|
|
198
|
-
model.set('/user/name', 'Eve');
|
|
199
|
-
|
|
200
|
-
assert.strictEqual(callCount1, 1);
|
|
201
|
-
assert.strictEqual(callCount2, 1);
|
|
202
|
-
assert.strictEqual(sub1.value, 'Eve');
|
|
203
|
-
assert.strictEqual(sub2.value, 'Eve');
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it('allows unsubscribing individual listeners', () => {
|
|
207
|
-
let callCount1 = 0;
|
|
208
|
-
let callCount2 = 0;
|
|
209
|
-
|
|
210
|
-
const sub1 = model.subscribe('/user/name', () => callCount1++);
|
|
211
|
-
|
|
212
|
-
const sub2 = model.subscribe('/user/name', () => callCount2++);
|
|
213
|
-
|
|
214
|
-
sub1.unsubscribe();
|
|
215
|
-
|
|
216
|
-
model.set('/user/name', 'Frank');
|
|
217
|
-
|
|
218
|
-
assert.strictEqual(callCount1, 0); // sub1 was unsubscribed
|
|
219
|
-
assert.strictEqual(callCount2, 1); // sub2 still active
|
|
220
|
-
assert.strictEqual(sub2.value, 'Frank');
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it('handles subscription to non-existent path', () => {
|
|
224
|
-
let val: any;
|
|
225
|
-
const sub = model.subscribe('/non/existent', (v) => val = v);
|
|
226
|
-
assert.strictEqual(sub.value, undefined);
|
|
227
|
-
|
|
228
|
-
model.set('/non/existent', 'exists now');
|
|
229
|
-
assert.strictEqual(sub.value, 'exists now');
|
|
230
|
-
assert.strictEqual(val, 'exists now');
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
it('handles updates to undefined', () => {
|
|
234
|
-
model.set('/foo', 'bar');
|
|
235
|
-
let val: any = 'initial';
|
|
236
|
-
const sub = model.subscribe('/foo', (v) => val = v);
|
|
237
|
-
|
|
238
|
-
model.set('/foo', undefined);
|
|
239
|
-
assert.strictEqual(sub.value, undefined);
|
|
240
|
-
assert.strictEqual(val, undefined);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('throws when trying to set nested property through a primitive', () => {
|
|
244
|
-
model.set('/user/name', 'not an object');
|
|
245
|
-
assert.strictEqual(model.get('/user/name'), 'not an object');
|
|
246
|
-
|
|
247
|
-
assert.throws(() => {
|
|
248
|
-
model.set('/user/name/first', 'Alice');
|
|
249
|
-
}, /Cannot set path/);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('throws when using non-numeric segment on an array', () => {
|
|
253
|
-
assert.throws(() => {
|
|
254
|
-
model.set('/items/foo', 'bar');
|
|
255
|
-
}, /Cannot use non-numeric segment/);
|
|
256
|
-
});
|
|
257
|
-
});
|
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright 2025 Google LLC
|
|
3
|
-
|
|
4
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
you may not use this file except in compliance with the License.
|
|
6
|
-
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
|
-
https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
See the License for the specific language governing permissions and
|
|
14
|
-
limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { Subscription as BaseSubscription } from '../common/events.js';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Represents a reactive connection to a specific path in the data model.
|
|
21
|
-
*/
|
|
22
|
-
export interface DataSubscription<T> extends BaseSubscription {
|
|
23
|
-
/**
|
|
24
|
-
* The current value at the subscribed path.
|
|
25
|
-
*/
|
|
26
|
-
readonly value: T | undefined;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
class SubscriptionImpl<T> implements DataSubscription<T> {
|
|
30
|
-
private _value: T | undefined;
|
|
31
|
-
private readonly _unsubscribe: () => void;
|
|
32
|
-
public onChange: (value: T | undefined) => void;
|
|
33
|
-
|
|
34
|
-
constructor(initialValue: T | undefined, onChange: (value: T | undefined) => void, unsubscribe: () => void) {
|
|
35
|
-
this._value = initialValue;
|
|
36
|
-
this.onChange = onChange;
|
|
37
|
-
this._unsubscribe = unsubscribe;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
get value(): T | undefined {
|
|
41
|
-
return this._value;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
setValue(value: T | undefined): void {
|
|
45
|
-
this._value = value;
|
|
46
|
-
this.onChange(value);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
unsubscribe(): void {
|
|
50
|
-
this._unsubscribe();
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function isNumeric(value: string): boolean {
|
|
55
|
-
return /^\d+$/.test(value);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* A standalone, observable data store representing the client-side state.
|
|
60
|
-
* It handles JSON Pointer path resolution and subscription management.
|
|
61
|
-
*/
|
|
62
|
-
export class DataModel {
|
|
63
|
-
private data: Record<string, unknown> = {};
|
|
64
|
-
private readonly subscriptions: Map<string, Set<SubscriptionImpl<any>>> = new Map();
|
|
65
|
-
|
|
66
|
-
constructor(initialData: Record<string, unknown> = {}) {
|
|
67
|
-
this.data = initialData;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Updates the model at the specific path and notifies all relevant subscribers.
|
|
72
|
-
* If path is '/' or empty, replaces the entire root.
|
|
73
|
-
*
|
|
74
|
-
* Note on `undefined` values:
|
|
75
|
-
* - For objects: Setting a property to `undefined` removes the key from the object.
|
|
76
|
-
* - For arrays: Setting an index to `undefined` sets that index to `undefined` but preserves the array length (sparse array).
|
|
77
|
-
*/
|
|
78
|
-
set(path: string, value: any): this {
|
|
79
|
-
if (path === null || path === undefined) {
|
|
80
|
-
throw new Error("Path cannot be null or undefined.");
|
|
81
|
-
}
|
|
82
|
-
if (path === '/' || path === '') {
|
|
83
|
-
this.data = value;
|
|
84
|
-
this.notifyAllSubscribers();
|
|
85
|
-
return this;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const segments = this.parsePath(path);
|
|
89
|
-
const lastSegment = segments.pop()!;
|
|
90
|
-
|
|
91
|
-
let current: any = this.data;
|
|
92
|
-
for (let i = 0; i < segments.length; i++) {
|
|
93
|
-
const segment = segments[i];
|
|
94
|
-
|
|
95
|
-
if (Array.isArray(current) && !isNumeric(segment)) {
|
|
96
|
-
throw new Error(`Cannot use non-numeric segment '${segment}' on an array in path '${path}'.`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// If we encounter a primitive where a container is expected, we cannot proceed.
|
|
100
|
-
// We allow undefined/null to be overwritten by a new container.
|
|
101
|
-
if (current[segment] !== undefined && current[segment] !== null && typeof current[segment] !== 'object') {
|
|
102
|
-
throw new Error(`Cannot set path '${path}': segment '${segment}' is a primitive value.`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (current[segment] === undefined || current[segment] === null) {
|
|
106
|
-
const nextSegment = (i < segments.length - 1) ? segments[i + 1] : lastSegment;
|
|
107
|
-
current[segment] = isNumeric(nextSegment) ? [] : {};
|
|
108
|
-
}
|
|
109
|
-
current = current[segment];
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (Array.isArray(current) && !isNumeric(lastSegment)) {
|
|
113
|
-
throw new Error(`Cannot use non-numeric segment '${lastSegment}' on an array in path '${path}'.`);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (value === undefined) {
|
|
117
|
-
if (Array.isArray(current)) {
|
|
118
|
-
current[parseInt(lastSegment, 10)] = undefined;
|
|
119
|
-
} else {
|
|
120
|
-
delete current[lastSegment];
|
|
121
|
-
}
|
|
122
|
-
} else {
|
|
123
|
-
current[lastSegment] = value;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
this.notifySubscribers(path);
|
|
127
|
-
return this;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Retrieves data at a specific path.
|
|
132
|
-
*/
|
|
133
|
-
get(path: string): any {
|
|
134
|
-
if (path === null || path === undefined) {
|
|
135
|
-
throw new Error("Path cannot be null or undefined.");
|
|
136
|
-
}
|
|
137
|
-
if (path === '/' || path === '') {
|
|
138
|
-
return this.data;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const segments = this.parsePath(path);
|
|
142
|
-
let current: any = this.data;
|
|
143
|
-
for (const segment of segments) {
|
|
144
|
-
if (current === undefined || current === null) {
|
|
145
|
-
return undefined;
|
|
146
|
-
}
|
|
147
|
-
current = current[segment];
|
|
148
|
-
}
|
|
149
|
-
return current;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Subscribes to changes at a specific path. Returns a Subscription object.
|
|
154
|
-
*/
|
|
155
|
-
subscribe<T>(path: string, onChange: (value: T | undefined) => void): DataSubscription<T> {
|
|
156
|
-
const normalizedPath = this.normalizePath(path);
|
|
157
|
-
const initialValue = this.get(normalizedPath);
|
|
158
|
-
|
|
159
|
-
const subscription = new SubscriptionImpl<T>(
|
|
160
|
-
initialValue,
|
|
161
|
-
onChange,
|
|
162
|
-
() => {
|
|
163
|
-
const set = this.subscriptions.get(normalizedPath);
|
|
164
|
-
if (set) {
|
|
165
|
-
set.delete(subscription);
|
|
166
|
-
if (set.size === 0) {
|
|
167
|
-
this.subscriptions.delete(normalizedPath);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
if (!this.subscriptions.has(normalizedPath)) {
|
|
174
|
-
this.subscriptions.set(normalizedPath, new Set());
|
|
175
|
-
}
|
|
176
|
-
this.subscriptions.get(normalizedPath)!.add(subscription);
|
|
177
|
-
|
|
178
|
-
return subscription;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Clears all internal subscriptions.
|
|
183
|
-
*/
|
|
184
|
-
dispose(): void {
|
|
185
|
-
this.subscriptions.clear();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private normalizePath(path: string): string {
|
|
189
|
-
if (path.length > 1 && path.endsWith('/')) {
|
|
190
|
-
return path.slice(0, -1);
|
|
191
|
-
}
|
|
192
|
-
return path || '/';
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
private parsePath(path: string): string[] {
|
|
196
|
-
return path.split('/').filter(p => p.length > 0);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
private notifySubscribers(path: string): void {
|
|
200
|
-
const normalizedPath = this.normalizePath(path);
|
|
201
|
-
this.notify(normalizedPath);
|
|
202
|
-
|
|
203
|
-
// Notify Ancestors
|
|
204
|
-
let parentPath = normalizedPath;
|
|
205
|
-
while (parentPath !== '/' && parentPath !== '') {
|
|
206
|
-
parentPath = parentPath.substring(0, parentPath.lastIndexOf('/')) || '/';
|
|
207
|
-
this.notify(parentPath);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Notify Descendants
|
|
211
|
-
for (const subPath of this.subscriptions.keys()) {
|
|
212
|
-
if (this.isDescendant(subPath, normalizedPath)) {
|
|
213
|
-
this.notify(subPath);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
private notify(path: string): void {
|
|
219
|
-
const set = this.subscriptions.get(path);
|
|
220
|
-
if (!set) {
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
const value = this.get(path);
|
|
224
|
-
set.forEach(sub => sub.setValue(value));
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
private notifyAllSubscribers(): void {
|
|
228
|
-
for (const path of this.subscriptions.keys()) {
|
|
229
|
-
this.notify(path);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
private isDescendant(childPath: string, parentPath: string): boolean {
|
|
234
|
-
if (parentPath === '/' || parentPath === '') {
|
|
235
|
-
return childPath !== '/';
|
|
236
|
-
}
|
|
237
|
-
return childPath.startsWith(parentPath + '/');
|
|
238
|
-
}
|
|
239
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
2
|
-
import { describe, it, beforeEach } from 'node:test';
|
|
3
|
-
import { SurfaceComponentsModel } from './surface-components-model.js';
|
|
4
|
-
import { ComponentModel } from './component-model.js';
|
|
5
|
-
|
|
6
|
-
describe('SurfaceComponentsModel', () => {
|
|
7
|
-
let model: SurfaceComponentsModel;
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
model = new SurfaceComponentsModel();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('starts empty', () => {
|
|
14
|
-
assert.strictEqual(model.get('any'), undefined);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('adds a new component', () => {
|
|
18
|
-
const c1 = new ComponentModel('c1', 'Button', { label: 'Click' });
|
|
19
|
-
model.addComponent(c1);
|
|
20
|
-
const retrieved = model.get('c1');
|
|
21
|
-
assert.ok(retrieved);
|
|
22
|
-
assert.strictEqual(retrieved?.id, 'c1');
|
|
23
|
-
assert.strictEqual(retrieved?.type, 'Button');
|
|
24
|
-
assert.strictEqual(retrieved?.properties.label, 'Click');
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('updates an existing component', () => {
|
|
28
|
-
const c1 = new ComponentModel('c1', 'Button', { label: 'Initial' });
|
|
29
|
-
model.addComponent(c1);
|
|
30
|
-
|
|
31
|
-
// Track update on component itself
|
|
32
|
-
let updateCount = 0;
|
|
33
|
-
c1.onUpdated.subscribe(() => { updateCount++; });
|
|
34
|
-
|
|
35
|
-
c1.properties = { label: 'Updated' };
|
|
36
|
-
|
|
37
|
-
assert.strictEqual(c1.properties.label, 'Updated');
|
|
38
|
-
assert.strictEqual(updateCount, 1);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('notifies on component creation', () => {
|
|
42
|
-
let createdComponent: ComponentModel | undefined;
|
|
43
|
-
model.onCreated.subscribe((c) => {
|
|
44
|
-
createdComponent = c;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
model.addComponent(new ComponentModel('c1', 'Button', {}));
|
|
48
|
-
assert.ok(createdComponent);
|
|
49
|
-
assert.strictEqual(createdComponent?.id, 'c1');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('throws when adding duplicate component', () => {
|
|
53
|
-
const c1 = new ComponentModel('c1', 'Button', {});
|
|
54
|
-
model.addComponent(c1);
|
|
55
|
-
assert.throws(() => {
|
|
56
|
-
model.addComponent(new ComponentModel('c1', 'Button', {}));
|
|
57
|
-
}, /already exists/);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { ComponentModel } from './component-model.js';
|
|
2
|
-
import { EventEmitter, EventSource } from '../common/events.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Manages the collection of components for a specific surface.
|
|
6
|
-
*/
|
|
7
|
-
export class SurfaceComponentsModel {
|
|
8
|
-
private components: Map<string, ComponentModel> = new Map();
|
|
9
|
-
|
|
10
|
-
private readonly _onCreated = new EventEmitter<ComponentModel>();
|
|
11
|
-
private readonly _onDeleted = new EventEmitter<string>();
|
|
12
|
-
|
|
13
|
-
/** Fires when a new component is added to the model. */
|
|
14
|
-
readonly onCreated: EventSource<ComponentModel> = this._onCreated;
|
|
15
|
-
/** Fires when a component is removed, providing the ID of the deleted component. */
|
|
16
|
-
readonly onDeleted: EventSource<string> = this._onDeleted;
|
|
17
|
-
|
|
18
|
-
get(id: string): ComponentModel | undefined {
|
|
19
|
-
return this.components.get(id);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
addComponent(component: ComponentModel): void {
|
|
23
|
-
if (this.components.has(component.id)) {
|
|
24
|
-
throw new Error(`Component with id '${component.id}' already exists.`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
this.components.set(component.id, component);
|
|
28
|
-
this._onCreated.emit(component);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
removeComponent(id: string): void {
|
|
32
|
-
const component = this.components.get(id);
|
|
33
|
-
if (component) {
|
|
34
|
-
this.components.delete(id);
|
|
35
|
-
component.dispose();
|
|
36
|
-
this._onDeleted.emit(id);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
dispose(): void {
|
|
41
|
-
for (const component of this.components.values()) {
|
|
42
|
-
component.dispose();
|
|
43
|
-
}
|
|
44
|
-
this.components.clear();
|
|
45
|
-
this._onCreated.dispose();
|
|
46
|
-
this._onDeleted.dispose();
|
|
47
|
-
}
|
|
48
|
-
}
|