@studio-piot/native-ui 0.16.0 → 0.20.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/README.md +13 -7
- package/dist/components/Choice/Choice.d.ts +6 -4
- package/dist/components/Choice/Choice.d.ts.map +1 -1
- package/dist/components/Choice/Choice.js +11 -5
- package/dist/components/Choice/Choice.js.map +1 -1
- package/dist/components/Choice/choiceLayout.d.ts +16 -0
- package/dist/components/Choice/choiceLayout.d.ts.map +1 -1
- package/dist/components/Choice/choiceLayout.js +20 -1
- package/dist/components/Choice/choiceLayout.js.map +1 -1
- package/dist/components/Choice/choiceThemeRoles.d.ts +1 -0
- package/dist/components/Choice/choiceThemeRoles.d.ts.map +1 -1
- package/dist/components/Choice/choiceThemeRoles.js +1 -0
- package/dist/components/Choice/choiceThemeRoles.js.map +1 -1
- package/dist/components/Choice/types.d.ts +7 -0
- package/dist/components/Choice/types.d.ts.map +1 -1
- package/dist/components/DateTime/DateTimePresenter.android.d.ts +4 -0
- package/dist/components/DateTime/DateTimePresenter.android.d.ts.map +1 -0
- package/dist/components/DateTime/DateTimePresenter.android.js +47 -0
- package/dist/components/DateTime/DateTimePresenter.android.js.map +1 -0
- package/dist/components/DateTime/DateTimePresenter.d.ts +4 -0
- package/dist/components/DateTime/DateTimePresenter.d.ts.map +1 -0
- package/dist/components/DateTime/DateTimePresenter.ios.d.ts +9 -0
- package/dist/components/DateTime/DateTimePresenter.ios.d.ts.map +1 -0
- package/dist/components/DateTime/DateTimePresenter.ios.js +69 -0
- package/dist/components/DateTime/DateTimePresenter.ios.js.map +1 -0
- package/dist/components/DateTime/DateTimePresenter.js +8 -0
- package/dist/components/DateTime/DateTimePresenter.js.map +1 -0
- package/dist/components/DateTime/FieldDateTime.d.ts +8 -0
- package/dist/components/DateTime/FieldDateTime.d.ts.map +1 -0
- package/dist/components/DateTime/FieldDateTime.js +90 -0
- package/dist/components/DateTime/FieldDateTime.js.map +1 -0
- package/dist/components/DateTime/dateTimeThemeRoles.d.ts +13 -0
- package/dist/components/DateTime/dateTimeThemeRoles.d.ts.map +1 -0
- package/dist/components/DateTime/dateTimeThemeRoles.js +15 -0
- package/dist/components/DateTime/dateTimeThemeRoles.js.map +1 -0
- package/dist/components/DateTime/dateTimeValue.d.ts +11 -0
- package/dist/components/DateTime/dateTimeValue.d.ts.map +1 -0
- package/dist/components/DateTime/dateTimeValue.js +40 -0
- package/dist/components/DateTime/dateTimeValue.js.map +1 -0
- package/dist/components/DateTime/index.d.ts +5 -0
- package/dist/components/DateTime/index.d.ts.map +1 -0
- package/dist/components/DateTime/index.js +10 -0
- package/dist/components/DateTime/index.js.map +1 -0
- package/dist/components/DateTime/types.d.ts +57 -0
- package/dist/components/DateTime/types.d.ts.map +1 -0
- package/dist/components/DateTime/types.js +3 -0
- package/dist/components/DateTime/types.js.map +1 -0
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +2 -9
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Tabs/Tabs.d.ts +8 -0
- package/dist/components/Tabs/Tabs.d.ts.map +1 -0
- package/dist/components/Tabs/Tabs.js +124 -0
- package/dist/components/Tabs/Tabs.js.map +1 -0
- package/dist/components/Tabs/index.d.ts +4 -0
- package/dist/components/Tabs/index.d.ts.map +1 -0
- package/dist/components/Tabs/index.js +8 -0
- package/dist/components/Tabs/index.js.map +1 -0
- package/dist/components/Tabs/tabsLayout.d.ts +13 -0
- package/dist/components/Tabs/tabsLayout.d.ts.map +1 -0
- package/dist/components/Tabs/tabsLayout.js +20 -0
- package/dist/components/Tabs/tabsLayout.js.map +1 -0
- package/dist/components/Tabs/tabsThemeRoles.d.ts +8 -0
- package/dist/components/Tabs/tabsThemeRoles.d.ts.map +1 -0
- package/dist/components/Tabs/tabsThemeRoles.js +10 -0
- package/dist/components/Tabs/tabsThemeRoles.js.map +1 -0
- package/dist/components/Tabs/types.d.ts +30 -0
- package/dist/components/Tabs/types.d.ts.map +1 -0
- package/dist/components/Tabs/types.js +3 -0
- package/dist/components/Tabs/types.js.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -2
- package/dist/components/index.js.map +1 -1
- package/dist/date-time.d.ts +6 -0
- package/dist/date-time.d.ts.map +1 -0
- package/dist/date-time.js +22 -0
- package/dist/date-time.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/layout/SheetContainer.d.ts +6 -0
- package/dist/layout/SheetContainer.d.ts.map +1 -0
- package/dist/layout/SheetContainer.js +14 -0
- package/dist/layout/SheetContainer.js.map +1 -0
- package/docs/components/choice.md +26 -3
- package/docs/components/field-date-time.md +89 -0
- package/docs/components/tabs.md +85 -0
- package/package.json +16 -2
- package/src/components/Choice/Choice.tsx +17 -6
- package/src/components/Choice/choiceLayout.test.ts +36 -1
- package/src/components/Choice/choiceLayout.ts +25 -0
- package/src/components/Choice/choiceThemeRoles.test.ts +1 -0
- package/src/components/Choice/choiceThemeRoles.ts +1 -0
- package/src/components/Choice/types.ts +7 -0
- package/src/components/DateTime/DateTimePresenter.android.tsx +76 -0
- package/src/components/DateTime/DateTimePresenter.ios.tsx +122 -0
- package/src/components/DateTime/DateTimePresenter.tsx +6 -0
- package/src/components/DateTime/FieldDateTime.tsx +164 -0
- package/src/components/DateTime/dateTimeThemeRoles.test.ts +18 -0
- package/src/components/DateTime/dateTimeThemeRoles.ts +13 -0
- package/src/components/DateTime/dateTimeValue.test.ts +49 -0
- package/src/components/DateTime/dateTimeValue.ts +36 -0
- package/src/components/DateTime/index.ts +4 -0
- package/src/components/DateTime/types.ts +58 -0
- package/src/components/Select/Select.tsx +1 -9
- package/src/components/Tabs/Tabs.tsx +148 -0
- package/src/components/Tabs/index.ts +3 -0
- package/src/components/Tabs/tabsLayout.test.ts +36 -0
- package/src/components/Tabs/tabsLayout.ts +23 -0
- package/src/components/Tabs/tabsThemeRoles.test.ts +14 -0
- package/src/components/Tabs/tabsThemeRoles.ts +8 -0
- package/src/components/Tabs/types.ts +31 -0
- package/src/components/index.ts +7 -0
- package/src/date-time.ts +5 -0
- package/src/index.ts +8 -1
- package/src/layout/SheetContainer.tsx +11 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
/**
|
|
18
|
+
* `@studio-piot/native-ui/date-time`: the date and time field. A separate
|
|
19
|
+
* entry so `@expo/ui`, which it needs, stays optional for apps without it.
|
|
20
|
+
*/
|
|
21
|
+
__exportStar(require("./components/DateTime"), exports);
|
|
22
|
+
//# sourceMappingURL=date-time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-time.js","sourceRoot":"","sources":["../src/date-time.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;GAGG;AACH,wDAAsC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const version = "0.
|
|
1
|
+
export declare const version = "0.20.0";
|
|
2
2
|
export * from "./theme";
|
|
3
3
|
export { SHEET_TOP_RADIUS, screenPaddingHorizontal } from "./layout";
|
|
4
4
|
export { Button, BUTTON_ICON_SIZE, BUTTON_THEME_ROLES, buttonRadiusValue, type ButtonIcon, type ButtonIconPosition, type ButtonProps, type ButtonRadius, type ButtonThemeColorProp, type ButtonVariant, } from "./components/Button";
|
|
@@ -15,6 +15,7 @@ export { Slider, SLIDER_THEME_ROLES, type SliderThemeColorProp, type SliderProps
|
|
|
15
15
|
export { HeaderCapsule, HeaderGroup, HeaderIcon, HEADER_BUTTON_THEME_ROLES, supportsLiquidGlass, type HeaderButtonThemeColorProp, type HeaderButtonIcon, type HeaderCapsuleProps, type HeaderGroupProps, type HeaderIconProps, } from "./components/HeaderButton";
|
|
16
16
|
export { HeaderWash } from "./components/HeaderWash";
|
|
17
17
|
export { TabAccessoryButton, TAB_ACCESSORY_SCREEN_INSET, TAB_ACCESSORY_THEME_ROLES, tabAccessoryScreenInset, type TabAccessoryButtonProps, type TabAccessoryPlacement, type TabAccessoryThemeColorProp, type TabAccessoryVariant, } from "./components/TabAccessoryButton";
|
|
18
|
+
export { Tabs, TABS_THEME_ROLES, type TabItem, type TabsProps, type TabsThemeColorProp, } from "./components/Tabs";
|
|
18
19
|
export { Page, PageBleed, PAGE_THEME_ROLES, type PageBleedProps, type PageProps, type PageTabAccessory, type PageThemeColorProp, } from "./components/Page";
|
|
19
20
|
export * as components from "./components";
|
|
20
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -37,8 +37,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.TAB_ACCESSORY_SCREEN_INSET = exports.TabAccessoryButton = exports.HeaderWash = exports.supportsLiquidGlass = exports.HEADER_BUTTON_THEME_ROLES = exports.HeaderIcon = exports.HeaderGroup = exports.HeaderCapsule = exports.SLIDER_THEME_ROLES = exports.Slider = exports.SEGMENTED_THEME_ROLES = exports.SegmentedControl = exports.resolveSelectDetentIndex = exports.detentsToSnapPoints = exports.DEFAULT_SELECT_INITIAL_DETENT = exports.DEFAULT_SELECT_DETENTS = exports.SELECT_THEME_ROLES = exports.SelectCloseButton = exports.Select = exports.RADIO_THEME_ROLES = exports.RadioField = exports.useErrorBannerField = exports.useErrorBannerDismiss = exports.useErrorBannerContext = exports.useErrorBanner = exports.ERROR_BANNER_THEME_ROLES = exports.ErrorBannerProvider = exports.ErrorBannerField = exports.ErrorBanner = exports.formSheetSnapPoints = exports.FORM_SHEET_THEME_ROLES = exports.FormSheet = exports.FORM_THEME_ROLES = exports.FormCloseButton = exports.Form = exports.FIELD_THEME_ROLES = exports.FieldTextarea = exports.FieldText = exports.filterLinkBlockGroups = exports.LinkBlocks = exports.CHOICE_THEME_ROLES = exports.CHOICE_ICON_SIZE = exports.Choice = exports.buttonRadiusValue = exports.BUTTON_THEME_ROLES = exports.BUTTON_ICON_SIZE = exports.Button = exports.screenPaddingHorizontal = exports.SHEET_TOP_RADIUS = exports.version = void 0;
|
|
40
|
-
exports.components = exports.PAGE_THEME_ROLES = exports.PageBleed = exports.Page = exports.tabAccessoryScreenInset = exports.TAB_ACCESSORY_THEME_ROLES = void 0;
|
|
41
|
-
exports.version = "0.
|
|
40
|
+
exports.components = exports.PAGE_THEME_ROLES = exports.PageBleed = exports.Page = exports.TABS_THEME_ROLES = exports.Tabs = exports.tabAccessoryScreenInset = exports.TAB_ACCESSORY_THEME_ROLES = void 0;
|
|
41
|
+
exports.version = "0.20.0";
|
|
42
42
|
__exportStar(require("./theme"), exports);
|
|
43
43
|
var layout_1 = require("./layout");
|
|
44
44
|
Object.defineProperty(exports, "SHEET_TOP_RADIUS", { enumerable: true, get: function () { return layout_1.SHEET_TOP_RADIUS; } });
|
|
@@ -106,6 +106,9 @@ Object.defineProperty(exports, "TabAccessoryButton", { enumerable: true, get: fu
|
|
|
106
106
|
Object.defineProperty(exports, "TAB_ACCESSORY_SCREEN_INSET", { enumerable: true, get: function () { return TabAccessoryButton_1.TAB_ACCESSORY_SCREEN_INSET; } });
|
|
107
107
|
Object.defineProperty(exports, "TAB_ACCESSORY_THEME_ROLES", { enumerable: true, get: function () { return TabAccessoryButton_1.TAB_ACCESSORY_THEME_ROLES; } });
|
|
108
108
|
Object.defineProperty(exports, "tabAccessoryScreenInset", { enumerable: true, get: function () { return TabAccessoryButton_1.tabAccessoryScreenInset; } });
|
|
109
|
+
var Tabs_1 = require("./components/Tabs");
|
|
110
|
+
Object.defineProperty(exports, "Tabs", { enumerable: true, get: function () { return Tabs_1.Tabs; } });
|
|
111
|
+
Object.defineProperty(exports, "TABS_THEME_ROLES", { enumerable: true, get: function () { return Tabs_1.TABS_THEME_ROLES; } });
|
|
109
112
|
var Page_1 = require("./components/Page");
|
|
110
113
|
Object.defineProperty(exports, "Page", { enumerable: true, get: function () { return Page_1.Page; } });
|
|
111
114
|
Object.defineProperty(exports, "PageBleed", { enumerable: true, get: function () { return Page_1.PageBleed; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAa,QAAA,OAAO,GAAG,QAAQ,CAAC;AAEhC,0CAAwB;AACxB,mCAAqE;AAA5D,0GAAA,gBAAgB,OAAA;AAAE,iHAAA,uBAAuB,OAAA;AAClD,8CAW6B;AAV3B,gGAAA,MAAM,OAAA;AACN,0GAAA,gBAAgB,OAAA;AAChB,4GAAA,kBAAkB,OAAA;AAClB,2GAAA,iBAAiB,OAAA;AAQnB,8CAM6B;AAL3B,gGAAA,MAAM,OAAA;AACN,0GAAA,gBAAgB,OAAA;AAChB,4GAAA,kBAAkB,OAAA;AAIpB,sDAMiC;AAL/B,wGAAA,UAAU,OAAA;AACV,mHAAA,qBAAqB,OAAA;AAKvB,4CAQ4B;AAP1B,kGAAA,SAAS,OAAA;AACT,sGAAA,aAAa,OAAA;AACb,0GAAA,iBAAiB,OAAA;AAMnB,0CAM2B;AALzB,4FAAA,IAAI,OAAA;AACJ,uGAAA,eAAe,OAAA;AACf,wGAAA,gBAAgB,OAAA;AAIlB,oDASgC;AAR9B,sGAAA,SAAS,OAAA;AACT,mHAAA,sBAAsB,OAAA;AACtB,gHAAA,mBAAmB,OAAA;AAOrB,wDAakC;AAZhC,0GAAA,WAAW,OAAA;AACX,+GAAA,gBAAgB,OAAA;AAChB,kHAAA,mBAAmB,OAAA;AACnB,uHAAA,wBAAwB,OAAA;AACxB,6GAAA,cAAc,OAAA;AACd,oHAAA,qBAAqB,OAAA;AACrB,oHAAA,qBAAqB,OAAA;AACrB,kHAAA,mBAAmB,OAAA;AAMrB,sDAMiC;AAL/B,wGAAA,UAAU,OAAA;AACV,+GAAA,iBAAiB,OAAA;AAKnB,8CAY6B;AAX3B,gGAAA,MAAM,OAAA;AACN,2GAAA,iBAAiB,OAAA;AACjB,4GAAA,kBAAkB,OAAA;AAClB,gHAAA,sBAAsB,OAAA;AACtB,uHAAA,6BAA6B,OAAA;AAC7B,6GAAA,mBAAmB,OAAA;AACnB,kHAAA,wBAAwB,OAAA;AAM1B,kEAMuC;AALrC,oHAAA,gBAAgB,OAAA;AAChB,yHAAA,qBAAqB,OAAA;AAKvB,8CAK6B;AAJ3B,gGAAA,MAAM,OAAA;AACN,4GAAA,kBAAkB,OAAA;AAIpB,0DAWmC;AAVjC,6GAAA,aAAa,OAAA;AACb,2GAAA,WAAW,OAAA;AACX,0GAAA,UAAU,OAAA;AACV,yHAAA,yBAAyB,OAAA;AACzB,mHAAA,mBAAmB,OAAA;AAOrB,sDAAqD;AAA5C,wGAAA,UAAU,OAAA;AACnB,sEASyC;AARvC,wHAAA,kBAAkB,OAAA;AAClB,gIAAA,0BAA0B,OAAA;AAC1B,+HAAA,yBAAyB,OAAA;AACzB,6HAAA,uBAAuB,OAAA;AAMzB,0CAQ2B;AAPzB,4FAAA,IAAI,OAAA;AACJ,iGAAA,SAAS,OAAA;AACT,wGAAA,gBAAgB,OAAA;AAMlB,2DAA2C"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAa,QAAA,OAAO,GAAG,QAAQ,CAAC;AAEhC,0CAAwB;AACxB,mCAAqE;AAA5D,0GAAA,gBAAgB,OAAA;AAAE,iHAAA,uBAAuB,OAAA;AAClD,8CAW6B;AAV3B,gGAAA,MAAM,OAAA;AACN,0GAAA,gBAAgB,OAAA;AAChB,4GAAA,kBAAkB,OAAA;AAClB,2GAAA,iBAAiB,OAAA;AAQnB,8CAM6B;AAL3B,gGAAA,MAAM,OAAA;AACN,0GAAA,gBAAgB,OAAA;AAChB,4GAAA,kBAAkB,OAAA;AAIpB,sDAMiC;AAL/B,wGAAA,UAAU,OAAA;AACV,mHAAA,qBAAqB,OAAA;AAKvB,4CAQ4B;AAP1B,kGAAA,SAAS,OAAA;AACT,sGAAA,aAAa,OAAA;AACb,0GAAA,iBAAiB,OAAA;AAMnB,0CAM2B;AALzB,4FAAA,IAAI,OAAA;AACJ,uGAAA,eAAe,OAAA;AACf,wGAAA,gBAAgB,OAAA;AAIlB,oDASgC;AAR9B,sGAAA,SAAS,OAAA;AACT,mHAAA,sBAAsB,OAAA;AACtB,gHAAA,mBAAmB,OAAA;AAOrB,wDAakC;AAZhC,0GAAA,WAAW,OAAA;AACX,+GAAA,gBAAgB,OAAA;AAChB,kHAAA,mBAAmB,OAAA;AACnB,uHAAA,wBAAwB,OAAA;AACxB,6GAAA,cAAc,OAAA;AACd,oHAAA,qBAAqB,OAAA;AACrB,oHAAA,qBAAqB,OAAA;AACrB,kHAAA,mBAAmB,OAAA;AAMrB,sDAMiC;AAL/B,wGAAA,UAAU,OAAA;AACV,+GAAA,iBAAiB,OAAA;AAKnB,8CAY6B;AAX3B,gGAAA,MAAM,OAAA;AACN,2GAAA,iBAAiB,OAAA;AACjB,4GAAA,kBAAkB,OAAA;AAClB,gHAAA,sBAAsB,OAAA;AACtB,uHAAA,6BAA6B,OAAA;AAC7B,6GAAA,mBAAmB,OAAA;AACnB,kHAAA,wBAAwB,OAAA;AAM1B,kEAMuC;AALrC,oHAAA,gBAAgB,OAAA;AAChB,yHAAA,qBAAqB,OAAA;AAKvB,8CAK6B;AAJ3B,gGAAA,MAAM,OAAA;AACN,4GAAA,kBAAkB,OAAA;AAIpB,0DAWmC;AAVjC,6GAAA,aAAa,OAAA;AACb,2GAAA,WAAW,OAAA;AACX,0GAAA,UAAU,OAAA;AACV,yHAAA,yBAAyB,OAAA;AACzB,mHAAA,mBAAmB,OAAA;AAOrB,sDAAqD;AAA5C,wGAAA,UAAU,OAAA;AACnB,sEASyC;AARvC,wHAAA,kBAAkB,OAAA;AAClB,gIAAA,0BAA0B,OAAA;AAC1B,+HAAA,yBAAyB,OAAA;AACzB,6HAAA,uBAAuB,OAAA;AAMzB,0CAM2B;AALzB,4FAAA,IAAI,OAAA;AACJ,wGAAA,gBAAgB,OAAA;AAKlB,0CAQ2B;AAPzB,4FAAA,IAAI,OAAA;AACJ,iGAAA,SAAS,OAAA;AACT,wGAAA,gBAAgB,OAAA;AAMlB,2DAA2C"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/** Renders a bottom sheet above React Navigation native modals (iOS). */
|
|
3
|
+
export declare function SheetContainer({ children }: {
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
}): import("react").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=SheetContainer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SheetContainer.d.ts","sourceRoot":"","sources":["../../src/layout/SheetContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,+BAKpE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SheetContainer = SheetContainer;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_native_1 = require("react-native");
|
|
6
|
+
const react_native_screens_1 = require("react-native-screens");
|
|
7
|
+
/** Renders a bottom sheet above React Navigation native modals (iOS). */
|
|
8
|
+
function SheetContainer({ children }) {
|
|
9
|
+
if (react_native_1.Platform.OS === "ios") {
|
|
10
|
+
return (0, jsx_runtime_1.jsx)(react_native_screens_1.FullWindowOverlay, { children: children });
|
|
11
|
+
}
|
|
12
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=SheetContainer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SheetContainer.js","sourceRoot":"","sources":["../../src/layout/SheetContainer.tsx"],"names":[],"mappings":";;AAKA,wCAKC;;AATD,+CAAwC;AACxC,+DAAyD;AAEzD,yEAAyE;AACzE,SAAgB,cAAc,CAAC,EAAE,QAAQ,EAA4B;IACnE,IAAI,uBAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,uBAAC,wCAAiB,cAAE,QAAQ,GAAqB,CAAC;IAC3D,CAAC;IACD,OAAO,2DAAG,QAAQ,GAAI,CAAC;AACzB,CAAC"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
One option in a list of next steps: an icon, a title and an optional description, in a filled row. Tapping it acts straight away, usually to open the next screen, as in "What are you doing? Running / HIIT".
|
|
4
4
|
|
|
5
|
-
Use `Choice` for a short list of destinations. To pick a value that stays on the screen, use [RadioField](./radio-field.md), [SegmentedControl](./segmented-control.md) or [Select](./select.md). For a settings list of links, use [LinkBlocks](./link-blocks.md).
|
|
5
|
+
Use `Choice` for a short list of destinations, or, with `selected`, for picking one of a few visual options such as candidate routes. To pick a value that stays on the screen, use [RadioField](./radio-field.md), [SegmentedControl](./segmented-control.md) or [Select](./select.md). For a settings list of links, use [LinkBlocks](./link-blocks.md).
|
|
6
6
|
|
|
7
7
|
## Basic usage
|
|
8
8
|
|
|
@@ -42,9 +42,29 @@ export default function NewActivity() {
|
|
|
42
42
|
- **Title only.** `description` is optional.
|
|
43
43
|
- **Spacing.** Put choices in a stack with a 16pt gap. The row has no margin of its own.
|
|
44
44
|
|
|
45
|
+
## Selectable choices
|
|
46
|
+
|
|
47
|
+
Pass `selected` to make the choices a set where one is picked, for example candidate routes with a drawing of each in the icon slot. The selected row gets a highlight border (`choiceSelected`); the others keep a transparent border of the same width, so nothing shifts when the selection moves. Tapping still calls `onPress`, where you update the selection.
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
{routes.map((route) => (
|
|
51
|
+
<Choice
|
|
52
|
+
key={route.id}
|
|
53
|
+
title={route.name}
|
|
54
|
+
description={`${route.km} km`}
|
|
55
|
+
icon={({ color, size }) => <RouteThumbnail route={route} color={color} size={size} />}
|
|
56
|
+
iconSize={48}
|
|
57
|
+
selected={route.id === selectedId}
|
|
58
|
+
onPress={() => setSelectedId(route.id)}
|
|
59
|
+
/>
|
|
60
|
+
))}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Pair it with one action that uses the selection, e.g. **Use this route**. Leave `selected` out when tapping should just act.
|
|
64
|
+
|
|
45
65
|
## Accessibility
|
|
46
66
|
|
|
47
|
-
The row is one button. VoiceOver reads its text together, for example "Running, Outdoors, with GPS, button". The icon is decorative and hidden from screen readers. `disabled` sets the disabled state, fades the row to 40% and blocks presses.
|
|
67
|
+
The row is one button. VoiceOver reads its text together, for example "Running, Outdoors, with GPS, button". With `selected`, it is a radio option instead, read as selected or not. The icon is decorative and hidden from screen readers. `disabled` sets the disabled state, fades the row to 40% and blocks presses.
|
|
48
68
|
|
|
49
69
|
## Theme roles
|
|
50
70
|
|
|
@@ -56,6 +76,7 @@ Add these keys to both the light and dark maps.
|
|
|
56
76
|
| Title | `choiceTitle` |
|
|
57
77
|
| Description | `choiceDescription` |
|
|
58
78
|
| Icon | `choiceIcon` |
|
|
79
|
+
| Selected border (with `selected`) | `choiceSelected` |
|
|
59
80
|
|
|
60
81
|
## Props
|
|
61
82
|
|
|
@@ -63,7 +84,8 @@ Add these keys to both the light and dark maps.
|
|
|
63
84
|
|---|---|---|---|
|
|
64
85
|
| `title` | `string` | — | Required |
|
|
65
86
|
| `onPress` | `() => void` | — | Required |
|
|
66
|
-
| `description` | `string` | — | Second line under the title |
|
|
87
|
+
| `description` | `string` | — | Second line under the title; may wrap to more lines |
|
|
88
|
+
| `selected` | `boolean` | — | Makes it a selectable option: highlight border when true, radio semantics |
|
|
67
89
|
| `icon` | `ButtonIcon` | — | `({ color, size }) => ReactNode` |
|
|
68
90
|
| `iconSize` | `number` | `28` | Icon box |
|
|
69
91
|
| `disabled` | `boolean` | `false` | 40% opacity; not pressable |
|
|
@@ -72,6 +94,7 @@ Add these keys to both the light and dark maps.
|
|
|
72
94
|
| `titleColor` | `string` | theme `choiceTitle` | Optional override |
|
|
73
95
|
| `descriptionColor` | `string` | theme `choiceDescription` | Optional override |
|
|
74
96
|
| `iconColor` | `string` | theme `choiceIcon` | Optional override |
|
|
97
|
+
| `selectedColor` | `string` | theme `choiceSelected` | Optional override |
|
|
75
98
|
| `style` | view style | — | Merged after the row |
|
|
76
99
|
|
|
77
100
|
Layout: 72pt minimum height, 16pt horizontal and 14pt vertical padding, 12pt between the icon and the text. The title is 17pt semibold and the description 13pt, the same as the rest of the package.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# FieldDateTime — usage
|
|
2
|
+
|
|
3
|
+
A date, time, or date-and-time field that matches `FieldText` and `Select`: label, value, description or error, and a `name` for the error banner. Tapping it opens the native picker:
|
|
4
|
+
|
|
5
|
+
- **iOS:** a bottom panel with SwiftUI's picker (a calendar for `date`, wheels for `time` and `datetime`) and **Done**. Tapping outside keeps the old value. It opens in a React Native `Modal`, so it works anywhere, including inside a sheet (`FormSheet`) or a native modal.
|
|
6
|
+
- **Android:** the system date dialog, then the time dialog for `datetime`.
|
|
7
|
+
|
|
8
|
+
## Import and peer dependency
|
|
9
|
+
|
|
10
|
+
`FieldDateTime` has its own entry, so apps without it don't need its native dependency:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx expo install @expo/ui
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { FieldDateTime } from "@studio-piot/native-ui/date-time";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`@expo/ui` is an optional peer of the package: only this entry uses it. No provider is needed.
|
|
21
|
+
|
|
22
|
+
## Basic usage
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
const [when, setWhen] = useState<Date | null>(null);
|
|
26
|
+
|
|
27
|
+
<FieldDateTime
|
|
28
|
+
name="when"
|
|
29
|
+
label="When are you running?"
|
|
30
|
+
value={when}
|
|
31
|
+
onChange={setWhen}
|
|
32
|
+
minimumDate={new Date()}
|
|
33
|
+
description="We'll remind you an hour before."
|
|
34
|
+
/>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- **Modes.** `mode="date"`, `"time"` or `"datetime"` (default).
|
|
38
|
+
- **Limits.** `minimumDate` / `maximumDate` limit the picker; a chosen value is also kept inside them.
|
|
39
|
+
- **Display.** Values show as "Sat 3 Oct 2026 · 08:05" (local time). Pass `formatValue` for your own wording, e.g. "Tomorrow · 08:00".
|
|
40
|
+
- **Empty.** With `value={null}` the field shows `placeholder` ("Choose a date" / "Choose a time").
|
|
41
|
+
- **Errors.** `error` shows under the field with an error border; with `name`, a banner row opens the picker.
|
|
42
|
+
|
|
43
|
+
## Theme roles
|
|
44
|
+
|
|
45
|
+
The same roles as `FieldText` and `Select`, so date fields match the form.
|
|
46
|
+
|
|
47
|
+
| Usage | Role |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Field fill, sheet | `fieldBackground` |
|
|
50
|
+
| Value, sheet title | `fieldText` |
|
|
51
|
+
| Placeholder, chevron, drag indicator | `fieldPlaceholder` |
|
|
52
|
+
| Label | `fieldLabel` |
|
|
53
|
+
| Description | `fieldDescription` |
|
|
54
|
+
| Border, sheet divider | `fieldBorder` |
|
|
55
|
+
| Error text and border | `fieldError` |
|
|
56
|
+
| Done, picker tint | `fieldSelectSelected` |
|
|
57
|
+
|
|
58
|
+
## Props
|
|
59
|
+
|
|
60
|
+
| Prop | Type | Default | Notes |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| `value` | `Date \| null` | — | Required |
|
|
63
|
+
| `onChange` | `(value: Date) => void` | — | Required. Called on Done (iOS) or when the dialogs finish (Android) |
|
|
64
|
+
| `mode` | `"date" \| "time" \| "datetime"` | `"datetime"` | |
|
|
65
|
+
| `name` | `string` | — | Error banner target |
|
|
66
|
+
| `label` | `string` | — | |
|
|
67
|
+
| `description` | `string` | — | |
|
|
68
|
+
| `error` | `string` | — | |
|
|
69
|
+
| `placeholder` | `string` | "Choose a date" / "Choose a time" | |
|
|
70
|
+
| `minimumDate` / `maximumDate` | `Date` | — | |
|
|
71
|
+
| `formatValue` | `(value: Date) => string` | "Sat 3 Oct 2026 · 08:05" | |
|
|
72
|
+
| `sheetTitle` | `string` | `label` | iOS sheet title |
|
|
73
|
+
| `doneLabel` | `string` | `"Done"` | |
|
|
74
|
+
| `radius` | `ButtonRadius` | `"xl"` | |
|
|
75
|
+
| `editable` | `boolean` | `true` | |
|
|
76
|
+
| Colour props | `string` | theme | `backgroundColor`, `textColor`, `placeholderColor`, `labelColor`, `descriptionColor`, `borderColor`, `errorColor`, `accentColor` |
|
|
77
|
+
| `style` | view style | — | |
|
|
78
|
+
|
|
79
|
+
## Imports
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
import {
|
|
83
|
+
FieldDateTime,
|
|
84
|
+
DATE_TIME_THEME_ROLES,
|
|
85
|
+
formatDateTimeValue,
|
|
86
|
+
type DateTimeMode,
|
|
87
|
+
type FieldDateTimeProps,
|
|
88
|
+
} from "@studio-piot/native-ui/date-time";
|
|
89
|
+
```
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Tabs — usage
|
|
2
|
+
|
|
3
|
+
Underline tabs that switch between views of the same screen, for example **Planned** and **Completed** on an Activities list. Equal-width labels sit on a hairline, and an underline slides to the active tab.
|
|
4
|
+
|
|
5
|
+
Tabs change what one screen shows; they don't navigate. For a choice inside a form, use [SegmentedControl](./segmented-control.md). For the app's main sections, use the native tab bar.
|
|
6
|
+
|
|
7
|
+
## Basic usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Page, Tabs } from "@studio-piot/native-ui";
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
|
|
13
|
+
type View = "planned" | "completed";
|
|
14
|
+
|
|
15
|
+
export default function Activities() {
|
|
16
|
+
const [view, setView] = useState<View>("planned");
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Page>
|
|
20
|
+
<Tabs
|
|
21
|
+
value={view}
|
|
22
|
+
onChange={setView}
|
|
23
|
+
tabs={[
|
|
24
|
+
{ value: "planned", label: "Planned" },
|
|
25
|
+
{ value: "completed", label: "Completed" },
|
|
26
|
+
]}
|
|
27
|
+
/>
|
|
28
|
+
{view === "planned" ? <PlannedList /> : <CompletedList />}
|
|
29
|
+
</Page>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- **Controlled.** Hold `value` in state; `onChange` gets the tapped tab's value.
|
|
35
|
+
- **Width.** Tabs fill their parent and share it equally. Inside a padded `Page`, the line runs between the page margins.
|
|
36
|
+
- **Edge-to-edge line.** To run the hairline across the whole screen while the tabs stay in line with the content, take the row to the edges with `PageBleed` and set `inset` to the page margin:
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
const { screen } = useThemeSpacing();
|
|
40
|
+
|
|
41
|
+
<PageBleed>
|
|
42
|
+
<Tabs inset={screen} value={view} onChange={setView} tabs={tabs} />
|
|
43
|
+
</PageBleed>
|
|
44
|
+
```
|
|
45
|
+
- **Icons.** Give a tab an `icon` render function, like `Button`'s, to show it left of the label. It gets the label's colour (active or inactive) and size 17; it's hidden from screen readers.
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
{ value: "planned", label: "Planned", icon: ({ color, size }) => <SymbolView name="calendar" size={size} tintColor={color} /> }
|
|
49
|
+
```
|
|
50
|
+
- **Disabled tabs** show at 40% and can't be pressed.
|
|
51
|
+
|
|
52
|
+
## Accessibility
|
|
53
|
+
|
|
54
|
+
The row is a tab list and each tab is a tab, with `selected` on the active one, so VoiceOver reads "Planned, tab, selected, 1 of 2".
|
|
55
|
+
|
|
56
|
+
## Theme roles
|
|
57
|
+
|
|
58
|
+
| Usage | Role |
|
|
59
|
+
|---|---|
|
|
60
|
+
| Hairline under the tabs | `tabsBorder` |
|
|
61
|
+
| Inactive label | `tabsLabel` |
|
|
62
|
+
| Active label | `tabsActiveLabel` |
|
|
63
|
+
| Sliding underline | `tabsIndicator` |
|
|
64
|
+
|
|
65
|
+
## Props
|
|
66
|
+
|
|
67
|
+
| Prop | Type | Default | Notes |
|
|
68
|
+
|---|---|---|---|
|
|
69
|
+
| `value` | `T` | — | Required. The active tab |
|
|
70
|
+
| `onChange` | `(value: T) => void` | — | Required |
|
|
71
|
+
| `tabs` | `TabItem<T>[]` | — | Required. `{ value, label, icon?, disabled? }`. Empty renders nothing |
|
|
72
|
+
| `inset` | `number` | `0` | Space each side for the tabs and underline; the hairline still spans the full width |
|
|
73
|
+
| `borderColor` | `string` | theme `tabsBorder` | Optional override |
|
|
74
|
+
| `labelColor` | `string` | theme `tabsLabel` | Optional override |
|
|
75
|
+
| `activeLabelColor` | `string` | theme `tabsActiveLabel` | Optional override |
|
|
76
|
+
| `indicatorColor` | `string` | theme `tabsIndicator` | Optional override |
|
|
77
|
+
| `style` | view style | — | The tab row |
|
|
78
|
+
|
|
79
|
+
Layout: labels 15pt semibold with 12pt above and below; the underline is 2pt and slides over 300ms. Uses `react-native-reanimated`, already a peer for `SegmentedControl` and `Select`.
|
|
80
|
+
|
|
81
|
+
## Imports
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { Tabs, TABS_THEME_ROLES, type TabItem, type TabsProps } from "@studio-piot/native-ui";
|
|
85
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@studio-piot/native-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Shared React Native components for Studio Piot apps.",
|
|
5
5
|
"homepage": "https://github.com/Studio-Piot/studio-native-ui#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -29,6 +29,13 @@
|
|
|
29
29
|
"import": "./dist/components/index.js",
|
|
30
30
|
"require": "./dist/components/index.js",
|
|
31
31
|
"default": "./dist/components/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./date-time": {
|
|
34
|
+
"types": "./dist/date-time.d.ts",
|
|
35
|
+
"react-native": "./dist/date-time.js",
|
|
36
|
+
"import": "./dist/date-time.js",
|
|
37
|
+
"require": "./dist/date-time.js",
|
|
38
|
+
"default": "./dist/date-time.js"
|
|
32
39
|
}
|
|
33
40
|
},
|
|
34
41
|
"typesVersions": {
|
|
@@ -50,6 +57,7 @@
|
|
|
50
57
|
"access": "public"
|
|
51
58
|
},
|
|
52
59
|
"peerDependencies": {
|
|
60
|
+
"@expo/ui": ">=57.0.0",
|
|
53
61
|
"@gorhom/bottom-sheet": "^5.2.14",
|
|
54
62
|
"@react-native-community/slider": "^5.2.0",
|
|
55
63
|
"react": ">=19.0.0",
|
|
@@ -67,9 +75,10 @@
|
|
|
67
75
|
"clean": "rm -rf dist *.tsbuildinfo",
|
|
68
76
|
"dev": "tsc --watch",
|
|
69
77
|
"prepare": "tsc",
|
|
70
|
-
"prepublishOnly": "
|
|
78
|
+
"prepublishOnly": "pnpm run build"
|
|
71
79
|
},
|
|
72
80
|
"devDependencies": {
|
|
81
|
+
"@expo/ui": "~57.0.19",
|
|
73
82
|
"@gorhom/bottom-sheet": "^5.2.14",
|
|
74
83
|
"@react-native-community/slider": "^5.2.0",
|
|
75
84
|
"@types/react": "^19.2.2",
|
|
@@ -81,5 +90,10 @@
|
|
|
81
90
|
"react-native-screens": "~4.26.0",
|
|
82
91
|
"react-native-svg": "^15.15.4",
|
|
83
92
|
"typescript": "^5.9.3"
|
|
93
|
+
},
|
|
94
|
+
"peerDependenciesMeta": {
|
|
95
|
+
"@expo/ui": {
|
|
96
|
+
"optional": true
|
|
97
|
+
}
|
|
84
98
|
}
|
|
85
99
|
}
|
|
@@ -2,20 +2,23 @@ import { Pressable, StyleSheet, Text, View } from "react-native";
|
|
|
2
2
|
import { buttonOpacity } from "../Button/buttonAppearance";
|
|
3
3
|
import { buttonRadiusValue } from "../Button/buttonRadius";
|
|
4
4
|
import { useResolvedFieldColor } from "../Field/useResolvedFieldColor";
|
|
5
|
-
import { CHOICE_ICON_SIZE, choiceIconSlot } from "./choiceLayout";
|
|
5
|
+
import { CHOICE_ICON_SIZE, choiceIconSlot, choiceSelection } from "./choiceLayout";
|
|
6
6
|
import { CHOICE_THEME_ROLES } from "./choiceThemeRoles";
|
|
7
7
|
import type { ChoiceProps } from "./types";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* One option in a list
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* One option in a list: an icon, a title and an optional description, in a
|
|
11
|
+
* filled row. Tapping it acts straight away (open the next screen), or,
|
|
12
|
+
* with `selected`, selects it among other choices (e.g. candidate routes,
|
|
13
|
+
* each with a drawing in the icon slot). For a form value, use RadioField
|
|
14
|
+
* or Select.
|
|
13
15
|
*/
|
|
14
16
|
export function Choice({
|
|
15
17
|
title,
|
|
16
18
|
description,
|
|
17
19
|
icon,
|
|
18
20
|
onPress,
|
|
21
|
+
selected,
|
|
19
22
|
disabled = false,
|
|
20
23
|
iconSize = CHOICE_ICON_SIZE,
|
|
21
24
|
radius = "xl",
|
|
@@ -23,6 +26,7 @@ export function Choice({
|
|
|
23
26
|
titleColor: titleColorProp,
|
|
24
27
|
descriptionColor: descriptionColorProp,
|
|
25
28
|
iconColor: iconColorProp,
|
|
29
|
+
selectedColor: selectedColorProp,
|
|
26
30
|
style,
|
|
27
31
|
}: ChoiceProps) {
|
|
28
32
|
const backgroundColor = useResolvedFieldColor(
|
|
@@ -41,20 +45,27 @@ export function Choice({
|
|
|
41
45
|
iconColorProp,
|
|
42
46
|
CHOICE_THEME_ROLES.iconColor,
|
|
43
47
|
);
|
|
48
|
+
const selectedColor = useResolvedFieldColor(
|
|
49
|
+
selectedColorProp,
|
|
50
|
+
CHOICE_THEME_ROLES.selectedColor,
|
|
51
|
+
);
|
|
44
52
|
const slot = choiceIconSlot(iconSize);
|
|
53
|
+
const selection = choiceSelection(selected);
|
|
45
54
|
|
|
46
55
|
return (
|
|
47
56
|
// No explicit label: the row groups its text, so VoiceOver reads the
|
|
48
57
|
// title and description together ("Running, Outdoors, with GPS, button").
|
|
49
58
|
<Pressable
|
|
50
|
-
accessibilityRole=
|
|
51
|
-
accessibilityState={{ disabled }}
|
|
59
|
+
accessibilityRole={selection.role}
|
|
60
|
+
accessibilityState={{ ...selection.state, disabled }}
|
|
52
61
|
disabled={disabled}
|
|
53
62
|
onPress={onPress}
|
|
54
63
|
style={({ pressed }) => [
|
|
55
64
|
styles.row,
|
|
56
65
|
{
|
|
57
66
|
backgroundColor,
|
|
67
|
+
borderColor: selection.highlighted ? selectedColor : "transparent",
|
|
68
|
+
borderWidth: selection.borderWidth,
|
|
58
69
|
borderRadius: buttonRadiusValue(radius),
|
|
59
70
|
opacity: buttonOpacity({ disabled, loading: false, pressed }),
|
|
60
71
|
},
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { describe, it } from "node:test";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
CHOICE_ICON_SIZE,
|
|
5
|
+
CHOICE_ICON_SLOT,
|
|
6
|
+
CHOICE_SELECTED_BORDER,
|
|
7
|
+
choiceIconSlot,
|
|
8
|
+
choiceSelection,
|
|
9
|
+
} from "./choiceLayout.ts";
|
|
4
10
|
|
|
5
11
|
describe("choiceIconSlot", () => {
|
|
6
12
|
it("keeps a steady slot so titles line up across rows", () => {
|
|
@@ -12,3 +18,32 @@ describe("choiceIconSlot", () => {
|
|
|
12
18
|
assert.equal(choiceIconSlot(40), 40);
|
|
13
19
|
});
|
|
14
20
|
});
|
|
21
|
+
|
|
22
|
+
describe("choiceSelection", () => {
|
|
23
|
+
it("is a plain button with no border when selection is not used", () => {
|
|
24
|
+
assert.deepEqual(choiceSelection(undefined), {
|
|
25
|
+
role: "button",
|
|
26
|
+
state: {},
|
|
27
|
+
borderWidth: 0,
|
|
28
|
+
highlighted: false,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("is a selected radio with the highlight border", () => {
|
|
33
|
+
assert.deepEqual(choiceSelection(true), {
|
|
34
|
+
role: "radio",
|
|
35
|
+
state: { selected: true, checked: true },
|
|
36
|
+
borderWidth: CHOICE_SELECTED_BORDER,
|
|
37
|
+
highlighted: true,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("keeps the border width when not selected, so rows do not jump", () => {
|
|
42
|
+
assert.deepEqual(choiceSelection(false), {
|
|
43
|
+
role: "radio",
|
|
44
|
+
state: { selected: false, checked: false },
|
|
45
|
+
borderWidth: CHOICE_SELECTED_BORDER,
|
|
46
|
+
highlighted: false,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -7,3 +7,28 @@ export const CHOICE_ICON_SLOT = 32;
|
|
|
7
7
|
export function choiceIconSlot(iconSize: number): number {
|
|
8
8
|
return Math.max(CHOICE_ICON_SLOT, iconSize);
|
|
9
9
|
}
|
|
10
|
+
|
|
11
|
+
/** Border around a selectable choice; drawn transparent when not selected. */
|
|
12
|
+
export const CHOICE_SELECTED_BORDER = 2;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Role, state and border for a choice. Without `selected` it is a plain
|
|
16
|
+
* button. With it, a radio option that keeps its border width either way,
|
|
17
|
+
* so rows do not shift when the selection moves. Pure so it can be unit-tested.
|
|
18
|
+
*/
|
|
19
|
+
export function choiceSelection(selected: boolean | undefined): {
|
|
20
|
+
role: "button" | "radio";
|
|
21
|
+
state: { selected?: boolean; checked?: boolean };
|
|
22
|
+
borderWidth: number;
|
|
23
|
+
highlighted: boolean;
|
|
24
|
+
} {
|
|
25
|
+
if (selected === undefined) {
|
|
26
|
+
return { role: "button", state: {}, borderWidth: 0, highlighted: false };
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
role: "radio",
|
|
30
|
+
state: { selected, checked: selected },
|
|
31
|
+
borderWidth: CHOICE_SELECTED_BORDER,
|
|
32
|
+
highlighted: selected,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -9,6 +9,11 @@ export type ChoiceProps = {
|
|
|
9
9
|
/** `({ color, size }) => ReactNode`, e.g. an expo-symbols `SymbolView`. */
|
|
10
10
|
icon?: ButtonIcon;
|
|
11
11
|
onPress: () => void;
|
|
12
|
+
/**
|
|
13
|
+
* Makes the choice a selectable option: a highlight border when true,
|
|
14
|
+
* read as a selected radio. Leave it out for a choice that just acts.
|
|
15
|
+
*/
|
|
16
|
+
selected?: boolean;
|
|
12
17
|
disabled?: boolean;
|
|
13
18
|
/** Icon box. Default 28. */
|
|
14
19
|
iconSize?: number;
|
|
@@ -22,5 +27,7 @@ export type ChoiceProps = {
|
|
|
22
27
|
descriptionColor?: string;
|
|
23
28
|
/** Defaults to theme role `choiceIcon`. */
|
|
24
29
|
iconColor?: string;
|
|
30
|
+
/** Border of a selected choice. Defaults to theme role `choiceSelected`. */
|
|
31
|
+
selectedColor?: string;
|
|
25
32
|
style?: StyleProp<ViewStyle>;
|
|
26
33
|
};
|