@use-voltra/core 2.0.0 → 2.1.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.
@@ -19,4 +19,5 @@ __exportStar(require("./payload.js"), exports);
19
19
  __exportStar(require("./payload/short-names.js"), exports);
20
20
  __exportStar(require("./renderer/index.js"), exports);
21
21
  __exportStar(require("./types.js"), exports);
22
+ __exportStar(require("./widget-environment.js"), exports);
22
23
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iEAA8C;AAC9C,+CAA4B;AAC5B,2DAAwC;AACxC,sDAAmC;AACnC,6CAA0B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iEAA8C;AAC9C,+CAA4B;AAC5B,2DAAwC;AACxC,sDAAmC;AACnC,6CAA0B;AAC1B,0DAAuC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isIosEnv = isIosEnv;
4
+ exports.isAndroidEnv = isAndroidEnv;
5
+ /**
6
+ * Type guard — returns true when the runtime env is an iOS-platform env.
7
+ *
8
+ * @example
9
+ * if (isIosEnv(env)) {
10
+ * // env.widgetRenderingMode is narrowed to the concrete value (not undefined)
11
+ * }
12
+ */
13
+ function isIosEnv(env) {
14
+ return env.widgetRenderingMode !== undefined;
15
+ }
16
+ /**
17
+ * Type guard — returns true when the runtime env is an Android-platform env.
18
+ *
19
+ * Android carries no platform-only runtime field (Material You colors are consumed via
20
+ * `AndroidDynamicColors` tokens resolved by the native renderer, not through `env`), so this is
21
+ * the complement of {@link isIosEnv}.
22
+ */
23
+ function isAndroidEnv(env) {
24
+ return !isIosEnv(env);
25
+ }
26
+ //# sourceMappingURL=widget-environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-environment.js","sourceRoot":"","sources":["../../src/widget-environment.ts"],"names":[],"mappings":";;AAkGA,4BAIC;AASD,oCAEC;AAvBD;;;;;;;GAOG;AACH,SAAgB,QAAQ,CACtB,GAAsB;IAEtB,OAAO,GAAG,CAAC,mBAAmB,KAAK,SAAS,CAAA;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAAC,GAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;AACvB,CAAC"}
@@ -3,4 +3,5 @@ export * from './payload.js';
3
3
  export * from './payload/short-names.js';
4
4
  export * from './renderer/index.js';
5
5
  export * from './types.js';
6
+ export * from './widget-environment.js';
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,cAAc,CAAA;AAC5B,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,cAAc,CAAA;AAC5B,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Type guard — returns true when the runtime env is an iOS-platform env.
3
+ *
4
+ * @example
5
+ * if (isIosEnv(env)) {
6
+ * // env.widgetRenderingMode is narrowed to the concrete value (not undefined)
7
+ * }
8
+ */
9
+ export function isIosEnv(env) {
10
+ return env.widgetRenderingMode !== undefined;
11
+ }
12
+ /**
13
+ * Type guard — returns true when the runtime env is an Android-platform env.
14
+ *
15
+ * Android carries no platform-only runtime field (Material You colors are consumed via
16
+ * `AndroidDynamicColors` tokens resolved by the native renderer, not through `env`), so this is
17
+ * the complement of {@link isIosEnv}.
18
+ */
19
+ export function isAndroidEnv(env) {
20
+ return !isIosEnv(env);
21
+ }
22
+ //# sourceMappingURL=widget-environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-environment.js","sourceRoot":"","sources":["../../src/widget-environment.ts"],"names":[],"mappings":"AA0FA;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CACtB,GAAsB;IAEtB,OAAO,GAAG,CAAC,mBAAmB,KAAK,SAAS,CAAA;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;AACvB,CAAC"}
@@ -3,4 +3,5 @@ export * from './payload.js';
3
3
  export * from './payload/short-names.js';
4
4
  export * from './renderer/index.js';
5
5
  export * from './types.js';
6
+ export * from './widget-environment.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,cAAc,CAAA;AAC5B,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,cAAc,CAAA;AAC5B,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Env shape consumed by Dynamic Widgets.
3
+ *
4
+ * Dynamic Widgets are functions of `(props, env) => JSX`, evaluated inside the
5
+ * Voltra JS runtime (JSC on iOS, Hermes on Android) at every render. The `env` second
6
+ * argument is populated by the native runtime at draw time and carries:
7
+ *
8
+ * - **Runtime device state** (`colorScheme`, `widgetFamily`, etc.) captured per render
9
+ * - **Platform-specific runtime state** (`widgetRenderingMode` on iOS), present only on the
10
+ * platform that has the concept
11
+ * - **AppIntent / user-configured params** under `env.configuration` (TypeScript-typed per
12
+ * widget via the generic parameter)
13
+ * - **Build env** under `env.build.*` — values that don't change between renders inside a
14
+ * process (isDev, Metro URL, app version, Voltra version)
15
+ *
16
+ * The shape mirrors expo-widgets' `WidgetEnvironment` for the runtime device fields, with
17
+ * a Voltra-specific `env.build.*` namespace added for dev-mode tooling.
18
+ *
19
+ * @typeParam TConfig - Shape of `env.configuration` (AppIntent / user-configured params).
20
+ * Defaults to `undefined` for widgets that don't accept user configuration. Widget authors
21
+ * can supply a more specific type per widget for typed access.
22
+ */
23
+ export type WidgetEnvironment<TConfig extends Record<string, unknown> | undefined = undefined> = {
24
+ /** Date the widget is being rendered for. Transported as epoch ms over the JS boundary
25
+ * and reconstructed as `Date` by the runtime entry. */
26
+ date: Date;
27
+ /** Widget size family. iOS values: `systemSmall`, `systemMedium`, `systemLarge`, etc.
28
+ * Android values: synthesized from Glance `LocalSize` (e.g. `"200x200"`). */
29
+ widgetFamily: string;
30
+ /** Current color scheme of the widget's environment. May be `undefined` if the platform
31
+ * doesn't expose it (rare). */
32
+ colorScheme?: 'light' | 'dark';
33
+ /** BCP-47 locale tag — for example `"en-US"` or `"pl-PL"`. */
34
+ locale?: string;
35
+ /** iOS — rendering mode the widget is being drawn in. `fullColor` on home screen,
36
+ * `accented` on tinted/Liquid Glass widgets (iOS 18+) and watchOS, `vibrant` on lock
37
+ * screen. Maps to SwiftUI `@Environment(\.widgetRenderingMode)`. */
38
+ widgetRenderingMode?: 'fullColor' | 'accented' | 'vibrant';
39
+ /** iOS — whether the system is drawing a container background behind the widget.
40
+ * Maps to SwiftUI `@Environment(\.showsWidgetContainerBackground)`. iOS 17+. */
41
+ showsWidgetContainerBackground?: boolean;
42
+ /** AppIntent / user-configured parameters for this widget. `undefined` for widgets that
43
+ * don't accept user configuration. Typed per widget via the [TConfig] generic. */
44
+ configuration: TConfig;
45
+ /** Build / process-level metadata, populated by the runtime once per process. Static for
46
+ * the JS runtime's lifetime; does not change between renders. */
47
+ build: WidgetBuildEnvironment;
48
+ };
49
+ /**
50
+ * Build / process metadata available inside the widget render function. Populated by the
51
+ * native runtime; identical across every render in a process.
52
+ */
53
+ export type WidgetBuildEnvironment = {
54
+ /** True when running against a development build (DEBUG / `__DEV__`). Used to gate
55
+ * dev-mode behaviour like fetching bundles from Metro. */
56
+ isDev: boolean;
57
+ /** URL of the Metro dev server when `isDev` is true. Used by the runtime to fetch widget
58
+ * bundles for hot-reload. `undefined` in release builds. */
59
+ metroUrl?: string;
60
+ /** App version string (`CFBundleShortVersionString` on iOS, `versionName` on Android). */
61
+ appVersion: string;
62
+ /** Voltra package version (`@use-voltra/core`). Surfaces in error reports and lets
63
+ * widgets gate behaviour by compatibility level if needed. */
64
+ voltraVersion: string;
65
+ };
66
+ /**
67
+ * Type guard — returns true when the runtime env is an iOS-platform env.
68
+ *
69
+ * @example
70
+ * if (isIosEnv(env)) {
71
+ * // env.widgetRenderingMode is narrowed to the concrete value (not undefined)
72
+ * }
73
+ */
74
+ export declare function isIosEnv(env: WidgetEnvironment): env is WidgetEnvironment & {
75
+ widgetRenderingMode: NonNullable<WidgetEnvironment['widgetRenderingMode']>;
76
+ };
77
+ /**
78
+ * Type guard — returns true when the runtime env is an Android-platform env.
79
+ *
80
+ * Android carries no platform-only runtime field (Material You colors are consumed via
81
+ * `AndroidDynamicColors` tokens resolved by the native renderer, not through `env`), so this is
82
+ * the complement of {@link isIosEnv}.
83
+ */
84
+ export declare function isAndroidEnv(env: WidgetEnvironment): boolean;
85
+ //# sourceMappingURL=widget-environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-environment.d.ts","sourceRoot":"","sources":["../../src/widget-environment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,iBAAiB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,SAAS,IAAI;IAC/F;2DACuD;IACvD,IAAI,EAAE,IAAI,CAAA;IAEV;iFAC6E;IAC7E,YAAY,EAAE,MAAM,CAAA;IAEpB;mCAC+B;IAC/B,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IAE9B,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAA;IAOf;;wEAEoE;IACpE,mBAAmB,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,SAAS,CAAA;IAE1D;oFACgF;IAChF,8BAA8B,CAAC,EAAE,OAAO,CAAA;IAMxC;sFACkF;IAClF,aAAa,EAAE,OAAO,CAAA;IAMtB;qEACiE;IACjE,KAAK,EAAE,sBAAsB,CAAA;CAC9B,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;8DAC0D;IAC1D,KAAK,EAAE,OAAO,CAAA;IAEd;gEAC4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,0FAA0F;IAC1F,UAAU,EAAE,MAAM,CAAA;IAElB;kEAC8D;IAC9D,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,iBAAiB,GACrB,GAAG,IAAI,iBAAiB,GAAG;IAAE,mBAAmB,EAAE,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,CAAC,CAAA;CAAE,CAE3G;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAE5D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@use-voltra/core",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "Generic renderer and payload utilities for Voltra",
5
5
  "main": "build/cjs/index.js",
6
6
  "module": "build/esm/index.js",
@@ -16,6 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "build",
19
+ "src",
19
20
  "README.md"
20
21
  ],
21
22
  "dependencies": {
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './jsx/createVoltraComponent.js'
2
+ export * from './payload.js'
3
+ export * from './payload/short-names.js'
4
+ export * from './renderer/index.js'
5
+ export * from './types.js'
6
+ export * from './widget-environment.js'
@@ -0,0 +1,36 @@
1
+ import type { ComponentType } from 'react'
2
+ import { createElement } from 'react'
3
+
4
+ export const VOLTRA_COMPONENT_TAG = Symbol.for('VOLTRA_COMPONENT_TAG')
5
+
6
+ export type VoltraComponent<TProps extends Record<string, unknown>> = ComponentType<TProps> & {
7
+ displayName: string
8
+ [VOLTRA_COMPONENT_TAG]: true
9
+ }
10
+
11
+ export type VoltraComponentOptions<TProps extends Record<string, unknown>> = {
12
+ toJSON?: (props: TProps) => Record<string, unknown>
13
+ }
14
+
15
+ export const createVoltraComponent = <TProps extends Record<string, unknown>>(
16
+ componentName: string,
17
+ options?: VoltraComponentOptions<TProps>
18
+ ): VoltraComponent<TProps> => {
19
+ const Component = (props: TProps) => {
20
+ const toJSON = options?.toJSON ? options.toJSON : (value: TProps) => value
21
+ const normalizedProps = toJSON(props)
22
+
23
+ return createElement(componentName, normalizedProps)
24
+ }
25
+
26
+ Component[VOLTRA_COMPONENT_TAG] = true
27
+ Component.displayName = componentName
28
+
29
+ return Component as VoltraComponent<TProps>
30
+ }
31
+
32
+ export const isVoltraComponent = <TProps extends Record<string, unknown>>(
33
+ component: ComponentType<TProps>
34
+ ): component is VoltraComponent<TProps> => {
35
+ return typeof component === 'function' && VOLTRA_COMPONENT_TAG in component
36
+ }
@@ -0,0 +1,379 @@
1
+ /* eslint-disable */
2
+ // 🤖 AUTO-GENERATED from data/components.json
3
+ // DO NOT EDIT MANUALLY - Changes will be overwritten
4
+ // Schema version: 1.0.0
5
+
6
+ /**
7
+ * Unified mapping from full names to short names
8
+ * Used for props and style properties
9
+ */
10
+ export const NAME_TO_SHORT: Record<string, string> = {
11
+ absolutePosition: 'ap',
12
+ accentedRenderingMode: 'arm',
13
+ alignItems: 'ai',
14
+ alignment: 'al',
15
+ alignSelf: 'as',
16
+ alpha: 'a',
17
+ aspectRatio: 'ar',
18
+ assetName: 'an',
19
+ background: 'bkg',
20
+ backgroundColor: 'bg',
21
+ backgroundImage: 'bgi',
22
+ backgroundStyle: 'bgs',
23
+ base64: 'b64',
24
+ border: 'bd',
25
+ borderColor: 'bc',
26
+ borderRadius: 'br',
27
+ borderWidth: 'bw',
28
+ bottom: 'b',
29
+ buttonStyle: 'bs',
30
+ chartScrollableAxes: 'csa',
31
+ checked: 'chk',
32
+ checkedColor: 'chc',
33
+ clipped: 'clip',
34
+ color: 'c',
35
+ colorFilter: 'cf',
36
+ colors: 'cls',
37
+ columns: 'cols',
38
+ contentAlignment: 'ca',
39
+ contentColor: 'cc',
40
+ contentDescription: 'cdesc',
41
+ contentScale: 'csc',
42
+ cornerRadius: 'cr',
43
+ countDown: 'cd',
44
+ currentValueLabel: 'cvl',
45
+ deepLinkUrl: 'dlu',
46
+ defaultValue: 'dv',
47
+ destination: 'dest',
48
+ direction: 'dir',
49
+ dither: 'dth',
50
+ durationMs: 'dur',
51
+ enabled: 'en',
52
+ endAtMs: 'end',
53
+ endPoint: 'ep',
54
+ fallback: 'flb',
55
+ fillMaxHeight: 'fmh',
56
+ fillMaxWidth: 'fmw',
57
+ fixedSizeHorizontal: 'fsh',
58
+ fixedSizeVertical: 'fsv',
59
+ flex: 'fl',
60
+ flexBasis: 'fb',
61
+ flexDirection: 'fdir',
62
+ flexGrow: 'fg',
63
+ flexGrowWidth: 'fgw',
64
+ flexShrink: 'fk',
65
+ font: 'fnt',
66
+ fontFamily: 'ff',
67
+ fontSize: 'fs',
68
+ fontVariant: 'fvar',
69
+ fontWeight: 'fw',
70
+ foregroundStyle: 'fgs',
71
+ foregroundStyleScale: 'fss',
72
+ frame: 'f',
73
+ gap: 'g',
74
+ gaugeStyle: 'gs',
75
+ glassEffect: 'ge',
76
+ height: 'h',
77
+ horizontalAlignment: 'halig',
78
+ horizontalPadding: 'hp',
79
+ icon: 'ic',
80
+ iconColor: 'icc',
81
+ id: 'id',
82
+ italic: 'it',
83
+ justifyContent: 'jc',
84
+ kerning: 'kern',
85
+ label: 'lbl',
86
+ layout: 'ly',
87
+ layoutPriority: 'lp',
88
+ left: 'l',
89
+ legendVisibility: 'lgv',
90
+ letterSpacing: 'ls',
91
+ lineHeight: 'lh',
92
+ lineLimit: 'll',
93
+ lineSpacing: 'lsp',
94
+ lineWidth: 'lw',
95
+ margin: 'm',
96
+ marginBottom: 'mb',
97
+ marginHorizontal: 'mh',
98
+ marginLeft: 'ml',
99
+ marginRight: 'mr',
100
+ marginTop: 'mt',
101
+ marginVertical: 'mv',
102
+ marks: 'mrk',
103
+ maskElement: 'me',
104
+ maxHeight: 'maxh',
105
+ maximumValue: 'max',
106
+ maximumValueLabel: 'maxl',
107
+ maxLines: 'mxl',
108
+ maxWidth: 'maxw',
109
+ minHeight: 'minh',
110
+ minimumValue: 'min',
111
+ minimumValueLabel: 'minvl',
112
+ minLength: 'minl',
113
+ minWidth: 'minw',
114
+ monospacedDigit: 'md',
115
+ multilineTextAlignment: 'mta',
116
+ name: 'n',
117
+ numberOfLines: 'nol',
118
+ offset: 'off',
119
+ offsetX: 'ox',
120
+ offsetY: 'oy',
121
+ opacity: 'op',
122
+ overflow: 'ov',
123
+ padding: 'pad',
124
+ paddingBottom: 'pb',
125
+ paddingHorizontal: 'ph',
126
+ paddingLeft: 'pl',
127
+ paddingRight: 'pr',
128
+ paddingTop: 'pt',
129
+ paddingVertical: 'pv',
130
+ position: 'pos',
131
+ progress: 'prg',
132
+ progressColor: 'pc',
133
+ resizeMode: 'rm',
134
+ right: 'r',
135
+ rotationEffect: 're',
136
+ scale: 'sc',
137
+ scaleEffect: 'sce',
138
+ shadow: 'sh',
139
+ shadowColor: 'shc',
140
+ shadowOffset: 'sho',
141
+ shadowOpacity: 'shop',
142
+ shadowRadius: 'shr',
143
+ showHours: 'shrs',
144
+ size: 'sz',
145
+ smallCaps: 'smc',
146
+ source: 'src',
147
+ spacing: 'sp',
148
+ startAtMs: 'start',
149
+ startIcon: 'sic',
150
+ startPoint: 'stp',
151
+ stops: 'sts',
152
+ strikethrough: 'st',
153
+ style: 's',
154
+ systemImage: 'si',
155
+ text: 'txt',
156
+ textAlign: 'ta',
157
+ textColor: 'txc',
158
+ textDecorationLine: 'tdl',
159
+ textStyle: 'ts',
160
+ textTemplates: 'tt',
161
+ thumb: 'th',
162
+ thumbCheckedColor: 'thc',
163
+ thumbUncheckedColor: 'thu',
164
+ tint: 'tnt',
165
+ tintColor: 'tc',
166
+ title: 'ttl',
167
+ top: 't',
168
+ trackCheckedColor: 'trkc',
169
+ trackColor: 'trc',
170
+ trackUncheckedColor: 'trku',
171
+ transform: 'tf',
172
+ type: 'typ',
173
+ uncheckedColor: 'uchc',
174
+ underline: 'ul',
175
+ value: 'v',
176
+ verticalAlignment: 'valig',
177
+ weight: 'wt',
178
+ width: 'w',
179
+ xAxisGridStyle: 'xgs',
180
+ xAxisVisibility: 'xav',
181
+ yAxisGridStyle: 'ygs',
182
+ yAxisVisibility: 'yav',
183
+ zIndex: 'zi',
184
+ }
185
+
186
+ /**
187
+ * Reverse mapping from short names to full names
188
+ */
189
+ export const SHORT_TO_NAME: Record<string, string> = {
190
+ ap: 'absolutePosition',
191
+ arm: 'accentedRenderingMode',
192
+ ai: 'alignItems',
193
+ al: 'alignment',
194
+ as: 'alignSelf',
195
+ a: 'alpha',
196
+ ar: 'aspectRatio',
197
+ an: 'assetName',
198
+ bkg: 'background',
199
+ bg: 'backgroundColor',
200
+ bgi: 'backgroundImage',
201
+ bgs: 'backgroundStyle',
202
+ b64: 'base64',
203
+ bd: 'border',
204
+ bc: 'borderColor',
205
+ br: 'borderRadius',
206
+ bw: 'borderWidth',
207
+ b: 'bottom',
208
+ bs: 'buttonStyle',
209
+ csa: 'chartScrollableAxes',
210
+ chk: 'checked',
211
+ chc: 'checkedColor',
212
+ clip: 'clipped',
213
+ c: 'color',
214
+ cf: 'colorFilter',
215
+ cls: 'colors',
216
+ cols: 'columns',
217
+ ca: 'contentAlignment',
218
+ cc: 'contentColor',
219
+ cdesc: 'contentDescription',
220
+ csc: 'contentScale',
221
+ cr: 'cornerRadius',
222
+ cd: 'countDown',
223
+ cvl: 'currentValueLabel',
224
+ dlu: 'deepLinkUrl',
225
+ dv: 'defaultValue',
226
+ dest: 'destination',
227
+ dir: 'direction',
228
+ dth: 'dither',
229
+ dur: 'durationMs',
230
+ en: 'enabled',
231
+ end: 'endAtMs',
232
+ ep: 'endPoint',
233
+ flb: 'fallback',
234
+ fmh: 'fillMaxHeight',
235
+ fmw: 'fillMaxWidth',
236
+ fsh: 'fixedSizeHorizontal',
237
+ fsv: 'fixedSizeVertical',
238
+ fl: 'flex',
239
+ fb: 'flexBasis',
240
+ fdir: 'flexDirection',
241
+ fg: 'flexGrow',
242
+ fgw: 'flexGrowWidth',
243
+ fk: 'flexShrink',
244
+ fnt: 'font',
245
+ ff: 'fontFamily',
246
+ fs: 'fontSize',
247
+ fvar: 'fontVariant',
248
+ fw: 'fontWeight',
249
+ fgs: 'foregroundStyle',
250
+ fss: 'foregroundStyleScale',
251
+ f: 'frame',
252
+ g: 'gap',
253
+ gs: 'gaugeStyle',
254
+ ge: 'glassEffect',
255
+ h: 'height',
256
+ halig: 'horizontalAlignment',
257
+ hp: 'horizontalPadding',
258
+ ic: 'icon',
259
+ icc: 'iconColor',
260
+ id: 'id',
261
+ it: 'italic',
262
+ jc: 'justifyContent',
263
+ kern: 'kerning',
264
+ lbl: 'label',
265
+ ly: 'layout',
266
+ lp: 'layoutPriority',
267
+ l: 'left',
268
+ lgv: 'legendVisibility',
269
+ ls: 'letterSpacing',
270
+ lh: 'lineHeight',
271
+ ll: 'lineLimit',
272
+ lsp: 'lineSpacing',
273
+ lw: 'lineWidth',
274
+ m: 'margin',
275
+ mb: 'marginBottom',
276
+ mh: 'marginHorizontal',
277
+ ml: 'marginLeft',
278
+ mr: 'marginRight',
279
+ mt: 'marginTop',
280
+ mv: 'marginVertical',
281
+ mrk: 'marks',
282
+ me: 'maskElement',
283
+ maxh: 'maxHeight',
284
+ max: 'maximumValue',
285
+ maxl: 'maximumValueLabel',
286
+ mxl: 'maxLines',
287
+ maxw: 'maxWidth',
288
+ minh: 'minHeight',
289
+ min: 'minimumValue',
290
+ minvl: 'minimumValueLabel',
291
+ minl: 'minLength',
292
+ minw: 'minWidth',
293
+ md: 'monospacedDigit',
294
+ mta: 'multilineTextAlignment',
295
+ n: 'name',
296
+ nol: 'numberOfLines',
297
+ off: 'offset',
298
+ ox: 'offsetX',
299
+ oy: 'offsetY',
300
+ op: 'opacity',
301
+ ov: 'overflow',
302
+ pad: 'padding',
303
+ pb: 'paddingBottom',
304
+ ph: 'paddingHorizontal',
305
+ pl: 'paddingLeft',
306
+ pr: 'paddingRight',
307
+ pt: 'paddingTop',
308
+ pv: 'paddingVertical',
309
+ pos: 'position',
310
+ prg: 'progress',
311
+ pc: 'progressColor',
312
+ rm: 'resizeMode',
313
+ r: 'right',
314
+ re: 'rotationEffect',
315
+ sc: 'scale',
316
+ sce: 'scaleEffect',
317
+ sh: 'shadow',
318
+ shc: 'shadowColor',
319
+ sho: 'shadowOffset',
320
+ shop: 'shadowOpacity',
321
+ shr: 'shadowRadius',
322
+ shrs: 'showHours',
323
+ sz: 'size',
324
+ smc: 'smallCaps',
325
+ src: 'source',
326
+ sp: 'spacing',
327
+ start: 'startAtMs',
328
+ sic: 'startIcon',
329
+ stp: 'startPoint',
330
+ sts: 'stops',
331
+ st: 'strikethrough',
332
+ s: 'style',
333
+ si: 'systemImage',
334
+ txt: 'text',
335
+ ta: 'textAlign',
336
+ txc: 'textColor',
337
+ tdl: 'textDecorationLine',
338
+ ts: 'textStyle',
339
+ tt: 'textTemplates',
340
+ th: 'thumb',
341
+ thc: 'thumbCheckedColor',
342
+ thu: 'thumbUncheckedColor',
343
+ tnt: 'tint',
344
+ tc: 'tintColor',
345
+ ttl: 'title',
346
+ t: 'top',
347
+ trkc: 'trackCheckedColor',
348
+ trc: 'trackColor',
349
+ trku: 'trackUncheckedColor',
350
+ tf: 'transform',
351
+ typ: 'type',
352
+ uchc: 'uncheckedColor',
353
+ ul: 'underline',
354
+ v: 'value',
355
+ valig: 'verticalAlignment',
356
+ wt: 'weight',
357
+ w: 'width',
358
+ xgs: 'xAxisGridStyle',
359
+ xav: 'xAxisVisibility',
360
+ ygs: 'yAxisGridStyle',
361
+ yav: 'yAxisVisibility',
362
+ zi: 'zIndex',
363
+ }
364
+
365
+ /**
366
+ * Shorten a name using the unified mapping
367
+ * Returns the original name if no short form exists
368
+ */
369
+ export function shorten(name: string): string {
370
+ return NAME_TO_SHORT[name] ?? name
371
+ }
372
+
373
+ /**
374
+ * Expand a short name back to the full name
375
+ * Returns the original value if no expansion exists
376
+ */
377
+ export function expand(short: string): string {
378
+ return SHORT_TO_NAME[short] ?? short
379
+ }
package/src/payload.ts ADDED
@@ -0,0 +1,23 @@
1
+ const MAX_ACTIVITYKIT_BYTES = 4096
2
+ const EFFECTIVE_JSON_BUDGET = 3345
3
+
4
+ const utf8ByteLength = (s: string): number => {
5
+ try {
6
+ if (typeof TextEncoder !== 'undefined') return new TextEncoder().encode(s).length
7
+ } catch {}
8
+ try {
9
+ return encodeURI(s).replace(/%[A-F\d]{2}/gi, 'X').length
10
+ } catch {
11
+ return s.length
12
+ }
13
+ }
14
+
15
+ export const ensurePayloadWithinBudget = (compressedPayload: string): void => {
16
+ const bytes = utf8ByteLength(compressedPayload)
17
+
18
+ if (bytes > EFFECTIVE_JSON_BUDGET) {
19
+ throw new Error(
20
+ `[Voltra] Compressed payload size ${bytes}B exceeds safe budget ${EFFECTIVE_JSON_BUDGET}B (ActivityKit hard cap ${MAX_ACTIVITYKIT_BYTES}B). You need to reduce the complexity of your UI.`
21
+ )
22
+ }
23
+ }