@symbiote-native/components 3.1.3 → 3.2.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.
@@ -0,0 +1 @@
1
+ export declare const CHECKMARK_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAACXBIWXMAFxGDABcRgwEFErJzAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAADY1JREFUeJzt3TuOrOtZhuGnFyKxnSMYgGWJKeBgyxFj2EhIZgxMAuQpIO0IOwXJ2hEQMAUSJEIExJDin4D12+vUq+vwvf93uq6wg9KjDvrWW9VVlQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAso7j+P3eGwCYzHEcPz2O49+O4/jj3lsAmMT7ePz38f/+U0QAeNMn8ThEBIA3vRIPEQHgdW/EQ0QA+NyN8RARAH7nzniICAAPx0NEAHb2ZDxEBGBHjeIhIgA7aRwPEQHYQVE8RARgZcXxEBGAFV0UDxEBWMnF8RARgBV0ioeIAMysczxEBGBGg8TjNEVEXnoPAOjtOI6fJvl1kh/13vKB/0rys5eXl3/pPeQ1AgJsbdB4nIaOiIAA2xo8HqdhIyIgwJYmicdpyIgICLCdyeJxGi4iAgJsZdJ4nIaKiIAA25g8HqdhIiIgwBYWicdpiIgICLC8xeJx6h4RAQGWtmg8Tl0jIiDAshaPx6lbRAQEWNIm8Th1iYiAAMvZLB6nyyMiIMBSNo3H6dKICAiwjM3jcbosIgICLEE8PnJJRAQEmJ54fFF5RAQEmJp4fFVpRAQEmJZ43KQsIgICTEk87lISEQEBpiMeD2keEQEBpiIeT2kaEQEBpiEeTTSLiIAAUxCPpppE5F2jMQBljuP4Jsn3EY9W/iDJz599EBcIMDSXR4lfJvmzl5eX/33mQQQEGJZ4lGgSj0RAgEGJR4lm8UgEBBiQeJRoGo9EQIDBiEeJ5vFIBAQYiHiUKIlHIiDAIMSjRFk8EgEBBiAeJUrjkQgI0Jl4lCiPRyIgQEfiUeKSeCQCAnQiHiUui0ciIEAH4lHi0ngkAgJcTDxKXB6PRECAC4lHiS7xSAQEuIh4lOgWj0RAgAuIR4mu8UgEBCgmHiW6xyMREKCQeJQYIh6JgABFxKPEMPFIBAQoIB4lhopHIiBAY+JRYrh4JAICNCQeJYaMRyIgQCPiUWLYeCQCAjQgHiWGjkciIMCTxKPE8PFIBAR4gniUmCIeiYAADxKPEtPEIxEQ4AHiUWKqeCQCAtxJPEpMF49EQIA7iEeJKeORCAhwI/EoMW08EgEBbiAeJaaORyIgwBvEo8T08UgEBPgK8SixRDwSAQFeIR4llolHIiDAF4hHiaXikQgI8AnxKLFcPBIBAT4gHiWWjEciIMB74lFi2XgkAgJEPIosHY9EQGB74lFi+XgkAgJbE48SW8QjERDYlniU2CYeiYDAlsSjxFbxSAQEtiMeJbaLRyIgsBXxKLFlPBIBgW2IR4lt45EICGxBPEpsHY9EQGB54lFi+3gkAgJLE48S4vGegMCixKOEeHxAQGBB4lFCPD4hILAY8SghHl8gILAQ8SghHq8QEFiEeJQQj68QEFiAeJQQjzcICExOPEqIxw0EBCYmHiXE40YCApMSjxLicQcBgQmJRwnxuJOAwGTEo4R4PEBAYCLiUUI8HiQgMAnxKCEeTxAQmIB4lBCPJwkIDE48SohHAwICAxOPEuLRiIDAoMSjhHg0JCAwIPEoIR6NCQgMRjxKiEcBAYGBiEcJ8SgiIDAI8SghHoUEBAYgHiXEo5iAQGfiUUI8LiAg0JF4lBCPiwgIdCIeJcTjQgICHYhHCfG4mIDAxcSjhHh0ICBwIfEoIR6dCAhcRDxKiEdHAgIXEI8S4tGZgEAx8SghHgMQECgkHiXEYxACAkXEo4R4DERAoIB4lBCPwQgINCYeJcRjQAICDYlHCfEYlIBAI+JRQjwGJiDQgHiUEI/BCQg8STxKiMcEBASeIB4lxGMSAgIPEo8S4jERAYEHiEcJ8ZiMgMCdxKOEeExIQOAO4lFCPCYlIHAj8SghHhMTELiBeJQQj8kJCLxBPEqIxwIEBL5CPEqIxyLe9R5wheM43h3H8ZfHcfyw9xbmcRzHN0m+j3i09F2Sb8VjDcsH5DiOd0n+JslfJfn+OA5/DHjT+8vj75L8oPeWhfwyyV+8vLz8pvcQ2lj6KawP4vHnH/z4n5P86cvLy//0WcXoPG1VwtNWC1o2IK/E4yQifJF4lBCPRS0ZkDficRIRPiIeJcRjYcsF5MZ4nESEJOJRRDwWt1RA7ozHSUQ2Jx4lxGMDywTkwXicRGRT4lFCPDaxRECejMdJRDYjHiXEYyPTB6RRPE4isgnxKCEem5k6II3jcRKRxYlHCfHY0LQBKYrHSUQWJR4lxGNTUwakOB4nEVmMeJQQj41NF5CL4nESkUWIRwnx2NxUAbk4HicRmZx4lBAP5glIp3icRGRS4lFCPEgySUA6x+MkIpMRjxLiwW8NH5BB4nESkUmIRwnx4CNDB2SweJxEZHDiUUI8+MywARk0HicRGZR4lBAPvmjIgAwej5OIDEY8SogHrxouIJPE4yQigxCPEuLBVw0VkMnicRKRzsSjhHjwpmECMmk8TiLSiXiUEA9uMkRAJo/HSUQuJh4lxIObdQ/IIvE4ichFxKOEeHCXrgFZLB4nESkmHiXEg7t1C8ii8TiJSBHxKCEePKRLQBaPx0lEGhOPEuLBwy4PyCbxOIlII+JRQjx4yqUB2SweJxF5kniUEA+edllANo3HSUQeJB4lxIMmLgnI5vE4icidxKOEeNBMeUDE4yMiciPxKCEeNFUaEPH4IhF5g3iUEA+aKwuIeHyViLxCPEqIByVKAiIeNxGRT4hHCfGgTPOAiMddROQ98SghHpRqGhDxeMj2ERGPEuJBuWYBEY+nbBsR8SghHlyiSUDEo4ntIiIeJcSDyzwdEPFoapuIiEcJ8eBS7xo8xl9HPFr5kyR/fxzHD3sPqXQcxzdJvo94tPRdkm/Fgyu1uEB+nOQfk/zR83N4b9lLxOVRwuVBF61eAxGR9paLiHiUEA+6aflfWCLS3jIREY8S4kFXrd8HIiLtTR8R8SghHnRX8U50EWlv2oiIRwnxYAhVn4UlIu1NFxHxKCEeDKPy03hFpL1pIiIeJcSDoVR/H4iItDd8RMSjhHgwnCu+kVBE2hs2IuJRQjwY0lXfiS4i7Q0XEfEoIR4M65KAJCJSZJiIiEcJ8WBolwUkEZEi3SMiHiXEg+FdGpBERIp0i4h4lBAPpnB5QBIRKXJ5RMSjhHgwjS4BSUSkyGUREY8S4sFUugUkEZEi5RERjxLiwXS6BiQRkSJlERGPEuLBlLoHJBGRIs0jIh4lxINpDRGQRESKNIuIeJQQD6Y2TEASESnydETEo4R4ML2hApKISJGHIyIeJcSDJQwXkEREitwdEfEoIR4sY8iAJCJS5OaIiEcJ8WApwwYkEZEib0ZEPEqIB8sZOiCJiBR5NSLiUUI8WNLwAUlEpMhnERGPEuLBsqYISCIiRX4bEfEoIR4sbZqAJMlxHD9J8g9J/rD3loX8U5JfJPlVkh/0nbKU75L8/OXl5Te9h0CVqQKSuESYgsuDLUwXkEREGJp4sI0pA5KICEMSD7YybUASEWEo4sF2pg5IIiIMQTzY0vQBSUSErsSDbS0RkERE6EI82NoyAUlEhEuJB9tbKiCJiHAJ8YAsGJBERCglHvDekgFJRIQS4gEfWDYgiYjQlHjAJ5YOSCIiNCEe8AXLByQREZ4iHvCKLQKSiAgPEQ/4im0CkogIdxEPeMNWAUlEhJuIB9xgu4AkIsJXiQfcaMuAJCLCF4kH3GHbgCQiwkfEA+60dUASESGJeMBDtg9IIiKbEw94kIC8JyJbEg94goB8QES2Ih7wJAH5hIhsQTygAQH5AhFZmnhAIwLyChFZknhAQwLyFSKyFPGAxgTkDSKyBPGAAgJyAxGZmnhAEQG5kYhMSTygkIDcQUSmIh5QTEDuJCJTEA+4gIA8QESGJh5wEQF5kIgMSTzgQgLyBBEZinjAxQTkSSIyBPGADgSkARHpSjygEwFpRES6EA/oSEAaEpFLiQd0JiCNicglxAMGICAFRKSUeMAg3vUesKKXl5d/TfKzJP/Re8tivkvyrXjAGFwghVwiTbk8YDACUkxEmhAPGJCAXEBEniIeMCgBuYiIPEQ8YGACciERuYt4wOAE5GIichPxgAkISAci8lXiAZMQkE5E5IvEAyYiIB2JyEfEAyYjIJ2JSBLxgCkJyAA2j4h4wKQEZBCbRkQ8YGICMpDNIiIeMDkBGcwmEREPWICADGjxiIgHLEJABrVoRMQDFiIgA1ssIuIBixGQwS0SEfGABQnIBCaPiHjAogRkEpNGRDxgYQIykckiIh6wOAGZzCQREQ+AER3H8ePjOP79GNPfHsfxe71/RwC84hgzIuIBMINjrIiIB8BMjjEiIh4AM+ocEfEAmFmniIgHwAoujoh4AKzkooiIB8CKiiMiHgArK4qIeADsoHFExANgJ40iIh4AO3oyIuIBsLMHIyIeANwdEfEA4HdujIh4APC5NyIiHgC87pWIiAcAb/skIuIBwO2O4/jJcRy/OI7jXe8tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA5/4PiZTk2kr08uAAAAAASUVORK5CYII=";
@@ -0,0 +1,2 @@
1
+ // Галочка из `ExpoCheckbox.tsx` как PNG data URI
2
+ export const CHECKMARK_URI = 'data:image/png;base64,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';
@@ -0,0 +1,3 @@
1
+ export declare const CHECKBOX_TAG = "checkbox";
2
+ export declare const CHECKBOX_MARK_TAG = "checkbox-mark";
3
+ export declare function registerCheckboxBehavior(): void;
@@ -0,0 +1,51 @@
1
+ // Checkbox как поведение engine-ноды, порт `ExpoCheckbox.tsx` из expo-checkbox
2
+ // Хост это Pressable, под ним картинка галочки, которую `buildStructure` строит один раз
3
+ // Вид (размер, рамка, цвета, display галочки) это правила тега в `SymbioteFabricProps.cpp`
4
+ // Регистрируют все пять адаптеров, см. `./pressable` про bare `import './register'`
5
+ import { appendChild, createElement, propOf, registerHostBehavior, setProp, } from '@symbiote-native/engine';
6
+ import { descriptorFor } from '../component-names';
7
+ import { CHECKMARK_URI } from './checkbox-checkmark.js';
8
+ import { createPressBehavior } from './pressable.js';
9
+ export const CHECKBOX_TAG = 'checkbox';
10
+ // Тег картинки галочки: правило в C++ читает `value` владельца и прячет её при false
11
+ export const CHECKBOX_MARK_TAG = 'checkbox-mark';
12
+ // Значение владельца меняет вид галочки, поэтому запись `value` помечает её грязной
13
+ const SLOT_DERIVED = ['value'];
14
+ function isValueChangeHandler(value) {
15
+ return typeof value === 'function';
16
+ }
17
+ // Нажатие заменяет любой `onPress` автора, как `onPress={handleChange}` в upstream
18
+ // `value` читается в момент нажатия, т.к. замыкание живёт дольше одного рендера
19
+ const toggleOnPress = (node, config) => ({
20
+ ...config,
21
+ onPress: event => {
22
+ const onValueChange = propOf(node, 'onValueChange');
23
+ if (isValueChangeHandler(onValueChange))
24
+ onValueChange(Object.assign(event, { value: !propOf(node, 'value') }));
25
+ },
26
+ });
27
+ // Возвращает ноду галочки как slot, т.к. `slotDerived` метит только слот
28
+ function buildStructure(node) {
29
+ const image = descriptorFor('image');
30
+ const mark = createElement(image.component, image.isText, CHECKBOX_MARK_TAG);
31
+ setProp(mark, 'source', { uri: CHECKMARK_URI });
32
+ appendChild(node, mark);
33
+ return mark;
34
+ }
35
+ // Идемпотентно: адаптер может импортироваться в бандле несколько раз
36
+ export function registerCheckboxBehavior() {
37
+ // Тег доходит до C++ только через регистрацию, пустая нужна и галочке
38
+ // `resolvesImageSources` свой у каждого тега: без него `source` уходит объектом, а не массивом
39
+ registerHostBehavior(CHECKBOX_MARK_TAG, {
40
+ resolvesImageSources: true,
41
+ attach() { },
42
+ detach() { },
43
+ });
44
+ registerHostBehavior(CHECKBOX_TAG, {
45
+ ...createPressBehavior(toggleOnPress),
46
+ buildStructure,
47
+ slotDerived: SLOT_DERIVED,
48
+ // Детей у checkbox нет, но без этого они ушли бы внутрь картинки
49
+ slotTakesNoChildren: true,
50
+ });
51
+ }
@@ -13,6 +13,7 @@ const ANDROID_NAMES = {
13
13
  'touchable-without-feedback': ANCHOR_COMPONENT,
14
14
  'touchable-highlight': 'RCTView',
15
15
  button: 'RCTView',
16
+ checkbox: 'RCTView',
16
17
  text: 'RCTText',
17
18
  image: 'RCTImageView',
18
19
  'image-background': 'RCTView',
@@ -15,6 +15,7 @@ const IOS_NAMES = {
15
15
  'touchable-without-feedback': ANCHOR_COMPONENT,
16
16
  'touchable-highlight': 'RCTView',
17
17
  button: 'RCTView',
18
+ checkbox: 'RCTView',
18
19
  text: 'RCTText',
19
20
  image: 'RCTImageView',
20
21
  'image-background': 'RCTView',
@@ -1,4 +1,4 @@
1
- export type ISymbioteIntrinsic = 'view' | 'pressable' | 'touchable-opacity' | 'touchable-native-feedback' | 'touchable-without-feedback' | 'touchable-highlight' | 'button' | 'text' | 'image' | 'image-background' | 'scroll-view' | 'scroll-content' | 'horizontal-scroll-view' | 'horizontal-scroll-content' | 'text-input' | 'text-input-multiline' | 'switch' | 'activity-indicator' | 'activity-indicator-spinner' | 'safe-area-view' | 'modal' | 'refresh-control' | 'sticky-header' | 'input-accessory-view';
1
+ export type ISymbioteIntrinsic = 'view' | 'pressable' | 'touchable-opacity' | 'touchable-native-feedback' | 'touchable-without-feedback' | 'touchable-highlight' | 'button' | 'checkbox' | 'text' | 'image' | 'image-background' | 'scroll-view' | 'scroll-content' | 'horizontal-scroll-view' | 'horizontal-scroll-content' | 'text-input' | 'text-input-multiline' | 'switch' | 'activity-indicator' | 'activity-indicator-spinner' | 'safe-area-view' | 'modal' | 'refresh-control' | 'sticky-header' | 'input-accessory-view';
2
2
  export type ICrossTypedIntrinsics<LooseProps, Crossed extends Partial<Record<ISymbioteIntrinsic, unknown>>> = Omit<Record<ISymbioteIntrinsic, LooseProps>, keyof Crossed> & Crossed;
3
3
  export interface IComponentDescriptor {
4
4
  component: string;
@@ -0,0 +1,20 @@
1
+ import type { ISymbioteNode } from '@symbiote-native/engine';
2
+ import type { IDescriptor } from './descriptor';
3
+ /** What a package builds for a native view: its handle and the descriptor it renders */
4
+ export type INativeViewController<THandle> = {
5
+ handle: THandle;
6
+ /** `null` means the view cannot render here and the caller paints nothing */
7
+ render(props: object): IDescriptor | null;
8
+ /** Called once when the view unmounts, for what the view holds besides its native node */
9
+ dispose?(): void;
10
+ };
11
+ /** `getNode` answers the host node of the view once it exists */
12
+ export type ICreateNativeViewController<THandle> = (getNode: () => ISymbioteNode | null) => INativeViewController<THandle>;
13
+ export type IHostNodeHolder = {
14
+ /** The host node the captured descriptor painted, `null` until it mounts */
15
+ getNode(): ISymbioteNode | null;
16
+ /** The descriptor with a `ref` that catches its host node, for React, Vue and Solid */
17
+ capture(descriptor: IDescriptor): IDescriptor;
18
+ };
19
+ /** Reaches the host node of a descriptor, which a component needs to call a native view function */
20
+ export declare function createHostNodeHolder(): IHostNodeHolder;
@@ -0,0 +1,16 @@
1
+ import { isSymbioteNode } from '@symbiote-native/engine';
2
+ /** Reaches the host node of a descriptor, which a component needs to call a native view function */
3
+ export function createHostNodeHolder() {
4
+ let node = null;
5
+ // One function for every capture, a changed `ref` would look like a changed prop
6
+ const hold = (host) => {
7
+ node = isSymbioteNode(host) ? host : null;
8
+ };
9
+ return {
10
+ getNode: () => node,
11
+ capture: descriptor => ({
12
+ ...descriptor,
13
+ props: { ...descriptor.props, ref: hold },
14
+ }),
15
+ };
16
+ }
package/build/index.d.ts CHANGED
@@ -2,6 +2,8 @@ export { el, txt } from './descriptor';
2
2
  export type { IDescriptor, IDescriptorType, IDescriptorProps, IDescriptorChild, } from './descriptor';
3
3
  export { createDescriptorShapeGuard } from './descriptor';
4
4
  export type { IDescriptorShapeGuard } from './descriptor';
5
+ export { createHostNodeHolder } from './host-node-holder';
6
+ export type { ICreateNativeViewController, IHostNodeHolder, INativeViewController, } from './host-node-holder';
5
7
  export { resolveAccessibilityProps } from './accessibility-props';
6
8
  export type { IEllipsizeMode } from './text-props';
7
9
  export type { IAccessibilityProps, IAriaProps, IAccessibilityRole, IRole, IAccessibilityStateValue, IAccessibilityValue, IAccessibilityActionInfo, } from './accessibility-props';
@@ -47,6 +49,7 @@ export type { ITextInputProps, ITextInputHandle, ITextInputSelection, ITextInput
47
49
  export { DEFAULT_WINDOW_SIZE, DEFAULT_INITIAL_NUM_TO_RENDER, DEFAULT_MAX_TO_RENDER_PER_BATCH, DEFAULT_UPDATE_CELLS_BATCHING_PERIOD, DEFAULT_VIEW_AREA_COVERAGE_PERCENT_THRESHOLD, FIRST_INDEX, EMPTY_OFFSET, NO_INDEX, NO_CONTENT_LENGTH_SENT, INVERTED_Y_STYLE, INVERTED_X_STYLE, readScrollOffset, readLayoutLength, readLayoutOffset, buildOffsets, computeWindow, throttleWindow, isCellViewable, offsetForIndex, averageMeasuredLength, averageMeasuredStride, highestMeasuredIndex, computeEndReached, computeStartReached, buildViewabilityPairs, computeViewableSet, diffViewable, maxMinimumViewTime, buildListPlan, computeMvcpAdjustment, resolveItemKey, indexOfItem, offsetForEnd, isSeparatorGapInRange, decideEdgeReached, resolveStickySectionHeaders, wrapFixedLayout, resolveAverageLength, } from './state/virtualized-list';
48
50
  export type { IMvcpAction, IMvcpAdjustmentParams, IMvcpAdjustmentResult, ICellLayout, ISeparators, ISeparatorProps, IViewToken, IViewableItemsChangedInfo, IViewabilityConfig, IViewabilityConfigCallbackPair, IVirtualizedListHandle, IViewableSetParams, IListCellPlan, IListPlan, IListPlanParams, } from './state/virtualized-list';
49
51
  export { reduceList, createInitialListState, listEffectSignature, } from './state/virtualized-list-reducer';
52
+ export { LIST_ACTION_KIND, LIST_EFFECT_KIND } from './state/list-kinds';
50
53
  export type { IListState, IListMetrics, IListReducerInputs, IListAction, IListEffect, IListReduceResult, } from './state/virtualized-list-reducer';
51
54
  export { subscribeListDiagnostics } from './state/virtualized-list-diagnostics';
52
55
  export type { IListDiagnosticFrame, IListDiagnosticMove, } from './state/virtualized-list-diagnostics';
@@ -58,6 +61,8 @@ export { registerPressableBehavior, PRESSABLE_TAG, } from './behaviors/pressable
58
61
  export { registerTouchableOpacityBehavior, TOUCHABLE_OPACITY_TAG, } from './behaviors/touchable-opacity';
59
62
  export { registerTouchableHighlightBehavior, TOUCHABLE_HIGHLIGHT_TAG, } from './behaviors/touchable-highlight';
60
63
  export { registerButtonBehavior, BUTTON_TAG } from './behaviors/button';
64
+ export { registerCheckboxBehavior, CHECKBOX_TAG, CHECKBOX_MARK_TAG, } from './behaviors/checkbox';
65
+ export type { ICheckboxProps, ICheckboxChangeEvent, } from './view/render-checkbox';
61
66
  export { registerTouchableNativeFeedbackBehavior, TOUCHABLE_NATIVE_FEEDBACK_TAG, } from './behaviors/touchable-native-feedback';
62
67
  export { registerTouchableWithoutFeedbackBehavior, TOUCHABLE_WITHOUT_FEEDBACK_TAG, } from './behaviors/touchable-without-feedback';
63
68
  export { ACTIVITY_INDICATOR_SPINNER_TAG, ACTIVITY_INDICATOR_TAG, registerActivityIndicatorBehavior, } from './behaviors/activity-indicator';
package/build/index.js CHANGED
@@ -7,6 +7,7 @@ export { el, txt } from './descriptor.js';
7
7
  // adapter bridges (Svelte's and Solid's), NOT part of an app's surface — so it stays out of the
8
8
  // adapter barrels, unlike the passthrough names in tests/adapter-barrel-parity.test.ts.
9
9
  export { createDescriptorShapeGuard } from './descriptor.js';
10
+ export { createHostNodeHolder } from './host-node-holder.js';
10
11
  // Accessibility folding: the web-alias (aria-*/role) → canonical accessibility* transform
11
12
  // and its types. Framework-agnostic, so React, Vue, and the next adapter all fold
12
13
  // identically; moved here from @symbiote-native/react. RefreshControl/SafeAreaView/ScrollView consume it.
@@ -71,6 +72,7 @@ export { DEFAULT_WINDOW_SIZE, DEFAULT_INITIAL_NUM_TO_RENDER, DEFAULT_MAX_TO_REND
71
72
  // after-commit effect skeleton (window recompute -> edge -> viewability -> initial-scroll -> MVCP)
72
73
  // out of each adapter's reactive glue. The adapter maps events to actions and runs the effects.
73
74
  export { reduceList, createInitialListState, listEffectSignature, } from './state/virtualized-list-reducer.js';
75
+ export { LIST_ACTION_KIND, LIST_EFFECT_KIND } from './state/list-kinds.js';
74
76
  export { subscribeListDiagnostics } from './state/virtualized-list-diagnostics.js';
75
77
  export { SINGLE_COLUMN, chunkIntoRows, rowKeyExtractor, expandRowToken, expandRowViewability, lastItemOfRow, firstItemOfRow, removeClippedSubviewsOrDefault, } from './state/flat-list.js';
76
78
  export { flattenSections, unwrapEntryItem, sectionEntryKey, scrollLocationToFlatIndex, } from './state/section-list.js';
@@ -78,6 +80,7 @@ export { registerPressableBehavior, PRESSABLE_TAG, } from './behaviors/pressable
78
80
  export { registerTouchableOpacityBehavior, TOUCHABLE_OPACITY_TAG, } from './behaviors/touchable-opacity.js';
79
81
  export { registerTouchableHighlightBehavior, TOUCHABLE_HIGHLIGHT_TAG, } from './behaviors/touchable-highlight.js';
80
82
  export { registerButtonBehavior, BUTTON_TAG } from './behaviors/button.js';
83
+ export { registerCheckboxBehavior, CHECKBOX_TAG, CHECKBOX_MARK_TAG, } from './behaviors/checkbox.js';
81
84
  // Registered by ALL FIVE adapters, in the same commit that deleted the five wrappers — safe
82
85
  // only because those wrappers no longer render their own Pressable, which would put a second
83
86
  // responder on every TouchableNativeFeedback.
package/build/register.js CHANGED
@@ -14,6 +14,7 @@
14
14
  // `register.test.ts` is what stops a later tidy-up from turning this back into an export.
15
15
  import { registerActivityIndicatorBehavior } from './behaviors/activity-indicator';
16
16
  import { registerButtonBehavior } from './behaviors/button.js';
17
+ import { registerCheckboxBehavior } from './behaviors/checkbox.js';
17
18
  import { registerImageBackgroundBehavior } from './behaviors/image-background.js';
18
19
  import { registerImageBehavior } from './behaviors/image.js';
19
20
  import { registerInputAccessoryViewBehavior } from './behaviors/input-accessory-view.js';
@@ -36,6 +37,8 @@ registerTouchableHighlightBehavior();
36
37
  // The whole subtree is the behavior's — RN's Button takes no children and builds
37
38
  // touchable > view > text > raw text itself (Button.js:363-388).
38
39
  registerButtonBehavior();
40
+ // A pressable box plus the checkmark image it builds under itself (expo-checkbox)
41
+ registerCheckboxBehavior();
39
42
  // Two nodes, both the behavior's: RN wraps its native spinner in a centering View
40
43
  // (ActivityIndicator.js:112), so the tag is that View and `buildStructure` builds the spinner.
41
44
  registerActivityIndicatorBehavior();
@@ -0,0 +1,22 @@
1
+ export declare const LIST_ACTION_KIND: {
2
+ readonly scroll: "scroll";
3
+ readonly layout: "layout";
4
+ readonly measure: "measure";
5
+ readonly refreshMetrics: "refresh-metrics";
6
+ readonly batchTick: "batch-tick";
7
+ readonly recordInteraction: "record-interaction";
8
+ readonly viewableFired: "viewable-fired";
9
+ readonly commit: "commit";
10
+ readonly scrollToOffset: "scroll-to-offset";
11
+ readonly scrollToIndex: "scroll-to-index";
12
+ readonly scrollToItem: "scroll-to-item";
13
+ readonly scrollToEnd: "scroll-to-end";
14
+ };
15
+ export declare const LIST_EFFECT_KIND: {
16
+ readonly scrollTo: "scroll-to";
17
+ readonly fireEndReached: "fire-end-reached";
18
+ readonly fireStartReached: "fire-start-reached";
19
+ readonly fireViewable: "fire-viewable";
20
+ readonly scheduleRefill: "schedule-refill";
21
+ readonly fireScrollToIndexFailed: "fire-scroll-to-index-failed";
22
+ };
@@ -0,0 +1,25 @@
1
+ // Names for the `kind` discriminants of the list reducer's actions and effects, so an adapter
2
+ // compares against a constant instead of repeating the string. `satisfies` keeps each value a
3
+ // real member of the union, a renamed kind stops compiling here
4
+ export const LIST_ACTION_KIND = {
5
+ scroll: 'scroll',
6
+ layout: 'layout',
7
+ measure: 'measure',
8
+ refreshMetrics: 'refresh-metrics',
9
+ batchTick: 'batch-tick',
10
+ recordInteraction: 'record-interaction',
11
+ viewableFired: 'viewable-fired',
12
+ commit: 'commit',
13
+ scrollToOffset: 'scroll-to-offset',
14
+ scrollToIndex: 'scroll-to-index',
15
+ scrollToItem: 'scroll-to-item',
16
+ scrollToEnd: 'scroll-to-end',
17
+ };
18
+ export const LIST_EFFECT_KIND = {
19
+ scrollTo: 'scroll-to',
20
+ fireEndReached: 'fire-end-reached',
21
+ fireStartReached: 'fire-start-reached',
22
+ fireViewable: 'fire-viewable',
23
+ scheduleRefill: 'schedule-refill',
24
+ fireScrollToIndexFailed: 'fire-scroll-to-index-failed',
25
+ };
@@ -0,0 +1,14 @@
1
+ import type { IColorValue, IStyleProp, IViewStyle, ISymbioteEvent } from '@symbiote-native/engine';
2
+ import type { IAccessibilityProps, IAriaProps } from '../accessibility-props';
3
+ export type ICheckboxChangeEvent = ISymbioteEvent & {
4
+ value: boolean;
5
+ };
6
+ export interface ICheckboxProps extends IAccessibilityProps, IAriaProps {
7
+ value?: boolean;
8
+ disabled?: boolean;
9
+ color?: IColorValue;
10
+ onChange?: (event: ISymbioteEvent) => void;
11
+ onValueChange?: (event: ICheckboxChangeEvent) => void;
12
+ style?: IStyleProp<IViewStyle>;
13
+ testID?: string;
14
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/components",
3
- "version": "3.1.3",
3
+ "version": "3.2.0",
4
4
  "description": "Framework-agnostic component logic (state machines + render functions) for SymbioteNative — written once, inherited by every adapter (React, Vue, Angular, ...).",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -59,11 +59,11 @@
59
59
  },
60
60
  "peerDependencies": {
61
61
  "react-native": ">=0.86",
62
- "@symbiote-native/engine": "^1.4.0"
62
+ "@symbiote-native/engine": "^1.6.0"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@types/node": "^26.0.0",
66
- "@symbiote-native/engine": "1.4.0"
66
+ "@symbiote-native/engine": "1.6.0"
67
67
  },
68
68
  "scripts": {
69
69
  "typecheck": "tsc --build",