@agimon-ai/po-native-components 0.0.0-alpha.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.
Files changed (122) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +71 -0
  3. package/dist/components/Badge.d.mts +17 -0
  4. package/dist/components/Badge.d.mts.map +1 -0
  5. package/dist/components/Badge.mjs +106 -0
  6. package/dist/components/Badge.mjs.map +1 -0
  7. package/dist/components/Button.d.mts +20 -0
  8. package/dist/components/Button.d.mts.map +1 -0
  9. package/dist/components/Button.mjs +278 -0
  10. package/dist/components/Button.mjs.map +1 -0
  11. package/dist/components/CodeBlock.d.mts +10 -0
  12. package/dist/components/CodeBlock.d.mts.map +1 -0
  13. package/dist/components/CodeBlock.mjs +88 -0
  14. package/dist/components/CodeBlock.mjs.map +1 -0
  15. package/dist/components/Dialog.d.mts +52 -0
  16. package/dist/components/Dialog.d.mts.map +1 -0
  17. package/dist/components/Dialog.mjs +257 -0
  18. package/dist/components/Dialog.mjs.map +1 -0
  19. package/dist/components/Dot.d.mts +17 -0
  20. package/dist/components/Dot.d.mts.map +1 -0
  21. package/dist/components/Dot.mjs +94 -0
  22. package/dist/components/Dot.mjs.map +1 -0
  23. package/dist/components/DropdownMenu.d.mts +63 -0
  24. package/dist/components/DropdownMenu.d.mts.map +1 -0
  25. package/dist/components/DropdownMenu.mjs +256 -0
  26. package/dist/components/DropdownMenu.mjs.map +1 -0
  27. package/dist/components/EmptyState.d.mts +14 -0
  28. package/dist/components/EmptyState.d.mts.map +1 -0
  29. package/dist/components/EmptyState.mjs +64 -0
  30. package/dist/components/EmptyState.mjs.map +1 -0
  31. package/dist/components/Input.d.mts +19 -0
  32. package/dist/components/Input.d.mts.map +1 -0
  33. package/dist/components/Input.mjs +123 -0
  34. package/dist/components/Input.mjs.map +1 -0
  35. package/dist/components/Label.d.mts +13 -0
  36. package/dist/components/Label.d.mts.map +1 -0
  37. package/dist/components/Label.mjs +36 -0
  38. package/dist/components/Label.mjs.map +1 -0
  39. package/dist/components/List.d.mts +48 -0
  40. package/dist/components/List.d.mts.map +1 -0
  41. package/dist/components/List.mjs +156 -0
  42. package/dist/components/List.mjs.map +1 -0
  43. package/dist/components/Markdown.d.mts +15 -0
  44. package/dist/components/Markdown.d.mts.map +1 -0
  45. package/dist/components/Markdown.mjs +219 -0
  46. package/dist/components/Markdown.mjs.map +1 -0
  47. package/dist/components/MessageItem.d.mts +87 -0
  48. package/dist/components/MessageItem.d.mts.map +1 -0
  49. package/dist/components/MessageItem.mjs +361 -0
  50. package/dist/components/MessageItem.mjs.map +1 -0
  51. package/dist/components/Panel.d.mts +15 -0
  52. package/dist/components/Panel.d.mts.map +1 -0
  53. package/dist/components/Panel.mjs +77 -0
  54. package/dist/components/Panel.mjs.map +1 -0
  55. package/dist/components/PoNativeProvider.d.mts +15 -0
  56. package/dist/components/PoNativeProvider.d.mts.map +1 -0
  57. package/dist/components/PoNativeProvider.mjs +22 -0
  58. package/dist/components/PoNativeProvider.mjs.map +1 -0
  59. package/dist/components/SectionLabel.d.mts +6 -0
  60. package/dist/components/SectionLabel.d.mts.map +1 -0
  61. package/dist/components/SectionLabel.mjs +40 -0
  62. package/dist/components/SectionLabel.mjs.map +1 -0
  63. package/dist/components/SegmentedControl.d.mts +26 -0
  64. package/dist/components/SegmentedControl.d.mts.map +1 -0
  65. package/dist/components/SegmentedControl.mjs +56 -0
  66. package/dist/components/SegmentedControl.mjs.map +1 -0
  67. package/dist/components/Sheet.d.mts +39 -0
  68. package/dist/components/Sheet.d.mts.map +1 -0
  69. package/dist/components/Sheet.mjs +166 -0
  70. package/dist/components/Sheet.mjs.map +1 -0
  71. package/dist/components/SheetFrame.mjs +84 -0
  72. package/dist/components/SheetFrame.mjs.map +1 -0
  73. package/dist/components/Spinner.d.mts +19 -0
  74. package/dist/components/Spinner.d.mts.map +1 -0
  75. package/dist/components/Spinner.mjs +34 -0
  76. package/dist/components/Spinner.mjs.map +1 -0
  77. package/dist/components/StatusBadge.d.mts +23 -0
  78. package/dist/components/StatusBadge.d.mts.map +1 -0
  79. package/dist/components/StatusBadge.mjs +116 -0
  80. package/dist/components/StatusBadge.mjs.map +1 -0
  81. package/dist/components/Tabs.d.mts +44 -0
  82. package/dist/components/Tabs.d.mts.map +1 -0
  83. package/dist/components/Tabs.mjs +197 -0
  84. package/dist/components/Tabs.mjs.map +1 -0
  85. package/dist/components/Textarea.d.mts +10 -0
  86. package/dist/components/Textarea.d.mts.map +1 -0
  87. package/dist/components/Textarea.mjs +29 -0
  88. package/dist/components/Textarea.mjs.map +1 -0
  89. package/dist/icons/IconColorContext.d.mts +10 -0
  90. package/dist/icons/IconColorContext.d.mts.map +1 -0
  91. package/dist/icons/IconColorContext.mjs +13 -0
  92. package/dist/icons/IconColorContext.mjs.map +1 -0
  93. package/dist/icons/iconGlyphs.d.mts +120 -0
  94. package/dist/icons/iconGlyphs.d.mts.map +1 -0
  95. package/dist/icons/iconGlyphs.mjs +121 -0
  96. package/dist/icons/iconGlyphs.mjs.map +1 -0
  97. package/dist/icons/icons.d.mts +122 -0
  98. package/dist/icons/icons.d.mts.map +1 -0
  99. package/dist/icons/icons.mjs +79 -0
  100. package/dist/icons/icons.mjs.map +1 -0
  101. package/dist/index.d.mts +27 -0
  102. package/dist/index.mjs +27 -0
  103. package/dist/lib/fonts.d.mts +13 -0
  104. package/dist/lib/fonts.d.mts.map +1 -0
  105. package/dist/lib/fonts.mjs +22 -0
  106. package/dist/lib/fonts.mjs.map +1 -0
  107. package/dist/lib/haptics.d.mts +7 -0
  108. package/dist/lib/haptics.d.mts.map +1 -0
  109. package/dist/lib/haptics.mjs +25 -0
  110. package/dist/lib/haptics.mjs.map +1 -0
  111. package/dist/lib/insideSheet.mjs +16 -0
  112. package/dist/lib/insideSheet.mjs.map +1 -0
  113. package/dist/lib/markdown.mjs +271 -0
  114. package/dist/lib/markdown.mjs.map +1 -0
  115. package/dist/lib/tone.mjs +50 -0
  116. package/dist/lib/tone.mjs.map +1 -0
  117. package/dist/lib/useControllable.mjs +22 -0
  118. package/dist/lib/useControllable.mjs.map +1 -0
  119. package/dist/lib/wrapText.mjs +20 -0
  120. package/dist/lib/wrapText.mjs.map +1 -0
  121. package/llms.txt +8 -0
  122. package/package.json +104 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vuong Ngo
4
+ Copyright (c) 2026 pulseaiclub
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # @agimon-ai/po-native-components
2
+
3
+ The React Native component library for Po's native client and its native plugins. It gives native
4
+ code the web library's look and API (`@agimon-ai/po-web-components`) built on native parts: the
5
+ platform activity indicator, Pressable with an Android ripple and 44pt tap targets, SF Symbols on
6
+ iOS and Material icons elsewhere, and a small haptics policy.
7
+
8
+ ## Use
9
+
10
+ Mount `PoNativeProvider` once at the app root, inside `SafeAreaProvider`. It supplies the gesture
11
+ handler root and the bottom sheet host that sheets, dialogs and menus need. Register Po's native
12
+ themes with Unistyles (`NATIVE_THEMES` from `@agimon-ai/po-web-components/nativeTheme`) before this
13
+ package is imported.
14
+
15
+ ```tsx
16
+ import { Button, PoNativeProvider } from '@agimon-ai/po-native-components';
17
+
18
+ <PoNativeProvider>
19
+ <Button variant="primary" onPress={save}>
20
+ Save
21
+ </Button>
22
+ </PoNativeProvider>;
23
+ ```
24
+
25
+ Plugins reach this package only through the native host module list. Its API is part of that host
26
+ contract, so it only ever grows: props and exports are added, never removed or renamed.
27
+
28
+ ## Catalogue
29
+
30
+ | Export | Web counterpart | Native behaviour |
31
+ | ----------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
32
+ | `Button` | Button (9 variants, 7 sizes) | Pressed state for hover, Android ripple, hitSlop to 44pt, light haptic on primary, danger and success |
33
+ | `Label`, `Input`, `Textarea` | Label, Input, Textarea | Placeholder in `faint`, jade cursor, autocorrect off, focus edge at 60% green |
34
+ | `Spinner` | Spinner | `ActivityIndicator` in a theme token; a labelled spinner is a live progress indicator |
35
+ | `Badge`, `StatusBadge`, `STATUS_EDGE`, `Dot` | Same | Accent edges at 40% alpha; `Dot` pulses with RN `Animated` |
36
+ | `EmptyState`, `SectionLabel`, `Panel`, `PanelHeader`, `PanelBody` | Same | Headings carry the header role |
37
+ | `List`, `ListRow` | None (the web uses card buttons) | FlashList; hairline separators, iOS disclosure chevron, selected rows on a green tint, `startAtBottom` for a chat list |
38
+ | `Sheet` and its parts | Sheet (`side` and `width` dropped) | `BottomSheetModal`: drag handle, sized to content, drag down, backdrop tap or Android back closes; fields inside switch to the sheet's own input |
39
+ | `Dialog` and its parts | Dialog (`width`, footer `plain` or `bar`) | RN `Modal` with an `Animated` pop; centred card; Android back and a backdrop tap close it |
40
+ | `DropdownMenu` and its parts | DropdownMenu (no submenus yet) | An action list in a bottom sheet; selection haptic; destructive items in red |
41
+ | `Tabs` and its parts, `TabBadge` | Tabs | Horizontal `ScrollView`; tab roles; active tab on a green tint; selection haptic |
42
+ | `SegmentedControl` | Select (task status) | segmented-control through `withUnistyles`; native on iOS, the library's fallback elsewhere |
43
+ | `CodeBlock` | CodeBlock (`text`, `language`) | Horizontal scroll, selectable mono text, expo-clipboard copy; no colouring or mermaid yet |
44
+ | `Markdown` | Markdown (`text`, `onFileLink`) | The package's own parser; links open with `Linking`; no tables, images or blockquotes yet |
45
+ | `MessageItem` and its parts, `toolTone`, `STATUS_LABEL` | MessageItem | The header is one Pressable that expands the item; edge from `STATUS_EDGE`; outcome as a `StatusBadge` |
46
+ | Icons (`CheckIcon` ... `CloseIcon`, 14) | icons.ts, same names | SF Symbols on iOS, MaterialIcons on Android and web |
47
+ | `PoNativeProvider` | None | `GestureHandlerRootView` and `BottomSheetModalProvider` |
48
+ | `fontOf`, `impactLight`, `selectionTick` | None | Per-platform font family; the haptics policy |
49
+
50
+ `asChild` has no native equivalent and is dropped. Colours always come from the Unistyles theme;
51
+ alpha mixes are computed in render because Unistyles hands stylesheets CSS variables on web.
52
+
53
+ ## Build
54
+
55
+ `tsdown` emits ESM only (`exports['.']` is `{types, default}`), unbundled, with every bare import
56
+ external, so each native library resolves from the app's single copy. The Unistyles Babel rewrite
57
+ runs at build time through `unistylesBabel` from `@agimon-ai/po-build/tsdown`.
58
+
59
+ ## Stories
60
+
61
+ Each component has a colocated `*.stories.tsx` titled `Native/Components/<Name>`, rendered from the
62
+ repository root:
63
+
64
+ ```sh
65
+ pnpm exec style-system get-ui-component -c 'Native/Components/Button' -a packages/core/po-native-components -s Playground
66
+ ```
67
+
68
+ `src/unistyles.ts` registers the themes for story renders only and is never exported. Story renders
69
+ run on react-native-web, so they cannot show SF Symbols, haptics or native ripples; check those on
70
+ a device. The SegmentedControl story does not render: style-system's bundler cannot parse the Flow
71
+ source segmented-control ships for its non-iOS fallback.
@@ -0,0 +1,17 @@
1
+ import { ChipTone } from "@agimon-ai/po-web-components/nativeTheme";
2
+ import { StyleProp, ViewProps, ViewStyle } from "react-native";
3
+ import { ReactNode } from "react";
4
+ //#region src/components/Badge.d.ts
5
+ export type BadgeTone = ChipTone;
6
+ export type BadgeSize = 'xs' | 'sm' | 'md' | 'lg';
7
+ export interface BadgeProps extends Omit<ViewProps, 'children' | 'style'> {
8
+ tone?: BadgeTone;
9
+ /** The same rungs Button names, so a chip can sit beside a button of any size. */
10
+ size?: BadgeSize;
11
+ children?: ReactNode;
12
+ style?: StyleProp<ViewStyle>;
13
+ }
14
+ /** An outlined chip in one of the accent tones. */
15
+ export declare function Badge({ tone, size, children, style, ...props }: BadgeProps): import("react").JSX.Element;
16
+ //#endregion
17
+ //# sourceMappingURL=Badge.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.d.mts","names":[],"sources":["../../src/components/Badge.tsx"],"mappings":";;;;YASY,YAAY;YACZ;iBAKK,mBAAmB,KAAK;EACvC,OAAO;;EAEP,OAAO;EACP,WAAW;EACX,QAAQ,UAAU;;;wBAIJ,QAAQ,MAAkB,MAAa,UAAU,UAAU,SAAS,6BAAU,IAAA"}
@@ -0,0 +1,106 @@
1
+ import { fontOf } from "../lib/fonts.mjs";
2
+ import { CHIP_INK } from "../lib/tone.mjs";
3
+ import { wrapText } from "../lib/wrapText.mjs";
4
+ import { View } from "react-native-unistyles/components/native/View";
5
+ import { withAlpha } from "@agimon-ai/po-web-components/nativeTheme";
6
+ import { StyleSheet, useUnistyles } from "react-native-unistyles";
7
+ import { jsx } from "react/jsx-runtime";
8
+
9
+ //#region src/components/Badge.tsx
10
+ /** `border-doom-<accent>/40`. */
11
+ const EDGE_ALPHA_PERCENT = 40;
12
+ /** An outlined chip in one of the accent tones. */
13
+ function Badge({ tone = "neutral", size = "sm", children, style, ...props }) {
14
+ const { theme } = useUnistyles();
15
+ const _styles = styles;
16
+ {
17
+ const styles = _styles.useVariants({
18
+ tone,
19
+ size
20
+ });
21
+ const edge = tone === "neutral" ? void 0 : { borderColor: withAlpha(theme.colors[CHIP_INK[tone]], EDGE_ALPHA_PERCENT) };
22
+ return /* @__PURE__ */ jsx(View, {
23
+ style: [
24
+ styles.badge,
25
+ edge,
26
+ style
27
+ ],
28
+ ...props,
29
+ children: wrapText(children, styles.label)
30
+ });
31
+ }
32
+ }
33
+ const styles = StyleSheet.create((theme) => {
34
+ const ink = (tone) => ({ color: theme.colors[CHIP_INK[tone]] });
35
+ return {
36
+ badge: {
37
+ flexDirection: "row",
38
+ alignItems: "center",
39
+ alignSelf: "flex-start",
40
+ gap: theme.spacing(1.5),
41
+ borderRadius: theme.borderRadius.DEFAULT,
42
+ borderWidth: 1,
43
+ borderColor: theme.colors.border,
44
+ variants: { size: {
45
+ xs: {
46
+ paddingHorizontal: theme.spacing(1.5),
47
+ paddingVertical: 1
48
+ },
49
+ sm: {
50
+ paddingHorizontal: theme.spacing(2),
51
+ paddingVertical: theme.spacing(.5)
52
+ },
53
+ md: {
54
+ paddingHorizontal: theme.spacing(2.5),
55
+ paddingVertical: theme.spacing(1)
56
+ },
57
+ lg: {
58
+ paddingHorizontal: theme.spacing(3),
59
+ paddingVertical: theme.spacing(1.5)
60
+ }
61
+ } },
62
+ uni__dependencies: [0, 4]
63
+ },
64
+ label: {
65
+ fontFamily: fontOf(theme.fontFamily.sans),
66
+ variants: {
67
+ tone: {
68
+ neutral: ink("neutral"),
69
+ blue: ink("blue"),
70
+ green: ink("green"),
71
+ yellow: ink("yellow"),
72
+ red: ink("red"),
73
+ magenta: ink("magenta"),
74
+ violet: ink("violet"),
75
+ cyan: ink("cyan"),
76
+ orange: ink("orange"),
77
+ teal: ink("teal")
78
+ },
79
+ size: {
80
+ xs: {
81
+ fontSize: theme.fontSize.sm,
82
+ lineHeight: theme.lineHeight.sm,
83
+ fontWeight: theme.fontWeight.semibold
84
+ },
85
+ sm: {
86
+ fontSize: theme.fontSize.sm,
87
+ lineHeight: theme.lineHeight.sm
88
+ },
89
+ md: {
90
+ fontSize: theme.fontSize.sm,
91
+ lineHeight: theme.lineHeight.sm
92
+ },
93
+ lg: {
94
+ fontSize: theme.fontSize.base,
95
+ lineHeight: theme.lineHeight.base
96
+ }
97
+ }
98
+ },
99
+ uni__dependencies: [0, 4]
100
+ }
101
+ };
102
+ });
103
+
104
+ //#endregion
105
+ export { Badge };
106
+ //# sourceMappingURL=Badge.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.mjs","names":["ChipTone","withAlpha","ReactNode","StyleProp","ViewProps","ViewStyle","StyleSheet","useUnistyles","fontOf","CHIP_INK","wrapText","BadgeTone","BadgeSize","EDGE_ALPHA_PERCENT","BadgeProps","Omit","tone","size","children","style","Badge","props","theme","_styles","styles","useVariants","edge","undefined","borderColor","colors","badge","label","create","ink","color","flexDirection","alignItems","alignSelf","gap","spacing","borderRadius","DEFAULT","borderWidth","border","variants","xs","paddingHorizontal","paddingVertical","sm","md","lg","uni__dependencies","fontFamily","sans","neutral","blue","green","yellow","red","magenta","violet","cyan","orange","teal","fontSize","lineHeight","fontWeight","semibold","base"],"sources":["../../src/components/Badge.tsx"],"sourcesContent":["import { type ChipTone, withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport type { ReactNode } from 'react';\nimport { type StyleProp, View, type ViewProps, type ViewStyle } from 'react-native';\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\n\nimport { fontOf } from '../lib/fonts';\nimport { CHIP_INK } from '../lib/tone';\nimport { wrapText } from '../lib/wrapText';\n\nexport type BadgeTone = ChipTone;\nexport type BadgeSize = 'xs' | 'sm' | 'md' | 'lg';\n\n/** `border-doom-<accent>/40`. */\nconst EDGE_ALPHA_PERCENT = 40;\n\nexport interface BadgeProps extends Omit<ViewProps, 'children' | 'style'> {\n tone?: BadgeTone;\n /** The same rungs Button names, so a chip can sit beside a button of any size. */\n size?: BadgeSize;\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/** An outlined chip in one of the accent tones. */\nexport function Badge({ tone = 'neutral', size = 'sm', children, style, ...props }: BadgeProps) {\n const { theme } = useUnistyles();\n styles.useVariants({ tone, size });\n // Alpha mixes are computed in render from useUnistyles(), not in StyleSheet.create: on web Unistyles hands\n // the stylesheet CSS variables, which withAlpha cannot read.\n const edge =\n tone === 'neutral' ? undefined : { borderColor: withAlpha(theme.colors[CHIP_INK[tone]], EDGE_ALPHA_PERCENT) };\n return (\n <View style={[styles.badge, edge, style]} {...props}>\n {wrapText(children, styles.label)}\n </View>\n );\n}\n\nconst styles = StyleSheet.create((theme) => {\n const ink = (tone: ChipTone) => ({ color: theme.colors[CHIP_INK[tone]] });\n return {\n badge: {\n flexDirection: 'row',\n alignItems: 'center',\n alignSelf: 'flex-start',\n gap: theme.spacing(1.5),\n borderRadius: theme.borderRadius.DEFAULT,\n borderWidth: 1,\n borderColor: theme.colors.border,\n variants: {\n size: {\n xs: { paddingHorizontal: theme.spacing(1.5), paddingVertical: 1 },\n sm: { paddingHorizontal: theme.spacing(2), paddingVertical: theme.spacing(0.5) },\n md: { paddingHorizontal: theme.spacing(2.5), paddingVertical: theme.spacing(1) },\n lg: { paddingHorizontal: theme.spacing(3), paddingVertical: theme.spacing(1.5) },\n },\n },\n },\n label: {\n fontFamily: fontOf(theme.fontFamily.sans),\n variants: {\n tone: {\n neutral: ink('neutral'),\n blue: ink('blue'),\n green: ink('green'),\n yellow: ink('yellow'),\n red: ink('red'),\n magenta: ink('magenta'),\n violet: ink('violet'),\n cyan: ink('cyan'),\n orange: ink('orange'),\n teal: ink('teal'),\n },\n size: {\n xs: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm, fontWeight: theme.fontWeight.semibold },\n sm: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm },\n md: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm },\n lg: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n },\n },\n },\n };\n});\n"],"mappings":";;;;;;;;;;AAaA,MAAMa,qBAAqB;;AAW3B,SAAgBO,MAAM,EAAEJ,OAAO,WAAWC,OAAO,MAAMC,UAAUC,OAAO,GAAGE,SAAqB;CAC9F,MAAM,EAAEC,UAAUf,aAAa;CAAE,MAAAgB,UAAAC;CAAA;EAAA,MAAAA,SAAAD,QAAAE,YACd;GAAET;GAAMC;EAAK,CAAC;EAGjC,MAAMS,OACJV,SAAS,YAAYW,SAAY,EAAEC,aAAa3B,UAAUqB,MAAMO,OAAOpB,SAASO,QAAQH,kBAAkB,EAAE;EAC9G,OACE,oBAAC,MAAD;GAAM,OAAO;IAACW,OAAOM;IAAOJ;IAAMP;GAAK;GAAG,GAAIE;aAC3CX,SAASQ,UAAUM,OAAOO,KAAK;EAC5B;CACN;AACJ;AAEA,MAAMP,SAASlB,WAAW0B,QAAQV,UAAU;CAC1C,MAAMW,OAAOjB,UAAoB,EAAEkB,OAAOZ,MAAMO,OAAOpB,SAASO,OAAO;CACvE,OAAO;EACLc,OAAO;GACLK,eAAe;GACfC,YAAY;GACZC,WAAW;GACXC,KAAKhB,MAAMiB,QAAQ,GAAG;GACtBC,cAAclB,MAAMkB,aAAaC;GACjCC,aAAa;GACbd,aAAaN,MAAMO,OAAOc;GAC1BC,UAAU,EACR3B,MAAM;IACJ4B,IAAI;KAAEC,mBAAmBxB,MAAMiB,QAAQ,GAAG;KAAGQ,iBAAiB;IAAE;IAChEC,IAAI;KAAEF,mBAAmBxB,MAAMiB,QAAQ,CAAC;KAAGQ,iBAAiBzB,MAAMiB,QAAQ,EAAG;IAAE;IAC/EU,IAAI;KAAEH,mBAAmBxB,MAAMiB,QAAQ,GAAG;KAAGQ,iBAAiBzB,MAAMiB,QAAQ,CAAC;IAAE;IAC/EW,IAAI;KAAEJ,mBAAmBxB,MAAMiB,QAAQ,CAAC;KAAGQ,iBAAiBzB,MAAMiB,QAAQ,GAAG;IAAE;GACjF,EACF;GAACY,mBAAA,CAAA,GAAA,CAAA;EACH;EACApB,OAAO;GACLqB,YAAY5C,OAAOc,MAAM8B,WAAWC,IAAI;GACxCT,UAAU;IACR5B,MAAM;KACJsC,SAASrB,IAAI,SAAS;KACtBsB,MAAMtB,IAAI,MAAM;KAChBuB,OAAOvB,IAAI,OAAO;KAClBwB,QAAQxB,IAAI,QAAQ;KACpByB,KAAKzB,IAAI,KAAK;KACd0B,SAAS1B,IAAI,SAAS;KACtB2B,QAAQ3B,IAAI,QAAQ;KACpB4B,MAAM5B,IAAI,MAAM;KAChB6B,QAAQ7B,IAAI,QAAQ;KACpB8B,MAAM9B,IAAI,MAAM;IAClB;IACAhB,MAAM;KACJ4B,IAAI;MAAEmB,UAAU1C,MAAM0C,SAAShB;MAAIiB,YAAY3C,MAAM2C,WAAWjB;MAAIkB,YAAY5C,MAAM4C,WAAWC;KAAS;KAC1GnB,IAAI;MAAEgB,UAAU1C,MAAM0C,SAAShB;MAAIiB,YAAY3C,MAAM2C,WAAWjB;KAAG;KACnEC,IAAI;MAAEe,UAAU1C,MAAM0C,SAAShB;MAAIiB,YAAY3C,MAAM2C,WAAWjB;KAAG;KACnEE,IAAI;MAAEc,UAAU1C,MAAM0C,SAASI;MAAMH,YAAY3C,MAAM2C,WAAWG;KAAK;IACzE;GACF;GAACjB,mBAAA,CAAA,GAAA,CAAA;EACH;CACF;AACF,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { PressableProps, StyleProp, ViewStyle } from "react-native";
2
+ import { ReactNode } from "react";
3
+ //#region src/components/Button.d.ts
4
+ export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'subtle' | 'danger' | 'danger-outline' | 'success' | 'link';
5
+ export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'icon' | 'icon-md' | 'card';
6
+ export interface ButtonProps extends Omit<PressableProps, 'children' | 'style'> {
7
+ variant?: ButtonVariant;
8
+ size?: ButtonSize;
9
+ /** Work is in flight: the button shows a spinner and stops accepting presses. */
10
+ loading?: boolean;
11
+ /** What the spinner announces while loading; omit it and the wait is silent. */
12
+ loadingLabel?: string;
13
+ /** A bare string is drawn as the label; elements (an icon, a card's lines) render as given. */
14
+ children?: ReactNode;
15
+ style?: StyleProp<ViewStyle>;
16
+ }
17
+ /** The one button: every variant is a theme token, a press dims or lifts it, and committing presses buzz once. */
18
+ export declare function Button({ variant, size, loading, loadingLabel, disabled, onPress, children, style, hitSlop, accessibilityState, ...props }: ButtonProps): import("react").JSX.Element;
19
+ //#endregion
20
+ //# sourceMappingURL=Button.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.d.mts","names":[],"sources":["../../src/components/Button.tsx"],"mappings":";;;YAWY;YAUA;iBAqCK,oBAAoB,KAAK;EACxC,UAAU;EACV,OAAO;;EAEP;;EAEA;;EAEA,WAAW;EACX,QAAQ,UAAU;;;wBAIJ,SACd,SACA,MACA,SACA,cACA,UACA,SACA,UACA,OACA,SACA,uBACG,SACF,8BAAW,IAAA"}
@@ -0,0 +1,278 @@
1
+ import { fontOf } from "../lib/fonts.mjs";
2
+ import { wrapText } from "../lib/wrapText.mjs";
3
+ import { IconColorContext } from "../icons/IconColorContext.mjs";
4
+ import { impactLight } from "../lib/haptics.mjs";
5
+ import { Spinner } from "./Spinner.mjs";
6
+ import { withAlpha } from "@agimon-ai/po-web-components/nativeTheme";
7
+ import { StyleSheet, useUnistyles } from "react-native-unistyles";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { Pressable } from "react-native-unistyles/components/native/Pressable";
10
+
11
+ //#region src/components/Button.tsx
12
+ /** Apple's and Google's minimum tap target; a smaller visual box makes up the rest with hitSlop. */
13
+ const MIN_TAP_TARGET = 44;
14
+ const DISABLED_OPACITY = .4;
15
+ const PRESSED_FILL_OPACITY = .85;
16
+ const RIPPLE_ALPHA_PERCENT = 20;
17
+ /** `hover:border-doom-green/50`. */
18
+ const PRESSED_EDGE_ALPHA_PERCENT = 50;
19
+ /** The visual height of each size, from which hitSlop pads the tap target to 44pt. */
20
+ const SIZE_HEIGHT = {
21
+ xs: 24,
22
+ sm: 28,
23
+ md: 32,
24
+ lg: 36,
25
+ icon: 24,
26
+ "icon-md": 32,
27
+ card: MIN_TAP_TARGET
28
+ };
29
+ /** The label ink of each variant, and the ink it lifts to while pressed (the web hover). */
30
+ const INK = {
31
+ primary: {
32
+ rest: "on-selected",
33
+ pressed: "on-selected"
34
+ },
35
+ secondary: {
36
+ rest: "magenta",
37
+ pressed: "magenta"
38
+ },
39
+ outline: {
40
+ rest: "dim",
41
+ pressed: "hi"
42
+ },
43
+ ghost: {
44
+ rest: "dim",
45
+ pressed: "hi"
46
+ },
47
+ subtle: {
48
+ rest: "dim",
49
+ pressed: "hi"
50
+ },
51
+ danger: {
52
+ rest: "rail",
53
+ pressed: "rail"
54
+ },
55
+ "danger-outline": {
56
+ rest: "red",
57
+ pressed: "red"
58
+ },
59
+ success: {
60
+ rest: "rail",
61
+ pressed: "rail"
62
+ },
63
+ link: {
64
+ rest: "blue",
65
+ pressed: "blue"
66
+ }
67
+ };
68
+ /** Presses that commit something get a light impact; the rest stay quiet. */
69
+ const HAPTIC_VARIANTS = /* @__PURE__ */ new Set([
70
+ "primary",
71
+ "danger",
72
+ "success"
73
+ ]);
74
+ /** The one button: every variant is a theme token, a press dims or lifts it, and committing presses buzz once. */
75
+ function Button({ variant = "outline", size = "md", loading = false, loadingLabel, disabled, onPress, children, style, hitSlop, accessibilityState, ...props }) {
76
+ const { theme } = useUnistyles();
77
+ const _styles = styles;
78
+ {
79
+ const styles = _styles.useVariants({
80
+ variant,
81
+ size
82
+ });
83
+ const inactive = (disabled ?? false) || loading;
84
+ const slop = Math.max(0, (MIN_TAP_TARGET - SIZE_HEIGHT[size]) / 2);
85
+ const ink = INK[variant];
86
+ return /* @__PURE__ */ jsx(Pressable, {
87
+ accessibilityRole: variant === "link" ? "link" : "button",
88
+ accessibilityState: {
89
+ ...accessibilityState,
90
+ disabled: inactive,
91
+ busy: loading
92
+ },
93
+ accessibilityValue: loading && loadingLabel !== void 0 ? { text: loadingLabel } : void 0,
94
+ disabled: inactive,
95
+ hitSlop: hitSlop ?? slop,
96
+ android_ripple: {
97
+ color: withAlpha(theme.colors[ink.pressed], RIPPLE_ALPHA_PERCENT),
98
+ borderless: false
99
+ },
100
+ onPress: (event) => {
101
+ if (HAPTIC_VARIANTS.has(variant)) impactLight();
102
+ onPress?.(event);
103
+ },
104
+ style: ({ pressed }) => [
105
+ styles.button,
106
+ pressed && styles.pressed,
107
+ pressed && variant === "outline" && { borderColor: withAlpha(theme.colors.green, PRESSED_EDGE_ALPHA_PERCENT) },
108
+ inactive && styles.disabled,
109
+ style
110
+ ],
111
+ ...props,
112
+ children: ({ pressed }) => {
113
+ const token = pressed ? ink.pressed : ink.rest;
114
+ return /* @__PURE__ */ jsxs(IconColorContext.Provider, {
115
+ value: token,
116
+ children: [loading ? /* @__PURE__ */ jsx(Spinner, { color: token }) : null, wrapText(children, [
117
+ styles.label,
118
+ pressed && styles.labelPressed,
119
+ { color: theme.colors[token] }
120
+ ])]
121
+ });
122
+ }
123
+ });
124
+ }
125
+ }
126
+ const styles = StyleSheet.create((theme) => ({
127
+ button: {
128
+ flexDirection: "row",
129
+ alignItems: "center",
130
+ justifyContent: "center",
131
+ gap: theme.spacing(1.5),
132
+ borderRadius: theme.borderRadius.md,
133
+ borderWidth: 1,
134
+ borderColor: "transparent",
135
+ overflow: "hidden",
136
+ variants: {
137
+ variant: {
138
+ primary: { backgroundColor: theme.colors.selected },
139
+ secondary: {
140
+ borderColor: theme.colors["edge-magenta"],
141
+ backgroundColor: theme.colors["tint-magenta"]
142
+ },
143
+ outline: { borderColor: theme.colors.border },
144
+ ghost: {},
145
+ subtle: { backgroundColor: theme.colors.panel },
146
+ danger: { backgroundColor: theme.colors.red },
147
+ "danger-outline": {
148
+ borderColor: theme.colors["edge-red"],
149
+ backgroundColor: theme.colors["tint-red"]
150
+ },
151
+ success: { backgroundColor: theme.colors.green },
152
+ link: {}
153
+ },
154
+ size: {
155
+ xs: {
156
+ height: SIZE_HEIGHT.xs,
157
+ paddingHorizontal: theme.spacing(1.5),
158
+ borderRadius: theme.borderRadius.DEFAULT
159
+ },
160
+ sm: {
161
+ height: SIZE_HEIGHT.sm,
162
+ paddingHorizontal: theme.spacing(2.5)
163
+ },
164
+ md: {
165
+ height: SIZE_HEIGHT.md,
166
+ paddingHorizontal: theme.spacing(3)
167
+ },
168
+ lg: {
169
+ height: SIZE_HEIGHT.lg,
170
+ paddingHorizontal: theme.spacing(3.5)
171
+ },
172
+ icon: {
173
+ width: SIZE_HEIGHT.icon,
174
+ height: SIZE_HEIGHT.icon,
175
+ padding: 0,
176
+ borderRadius: theme.borderRadius.DEFAULT
177
+ },
178
+ "icon-md": {
179
+ width: SIZE_HEIGHT["icon-md"],
180
+ height: SIZE_HEIGHT["icon-md"],
181
+ padding: 0
182
+ },
183
+ card: {
184
+ alignSelf: "stretch",
185
+ flexDirection: "column",
186
+ alignItems: "stretch",
187
+ justifyContent: "flex-start",
188
+ gap: theme.spacing(1),
189
+ minHeight: SIZE_HEIGHT.card,
190
+ paddingHorizontal: 11,
191
+ paddingVertical: theme.spacing(2.5)
192
+ }
193
+ }
194
+ },
195
+ uni__dependencies: [0, 4]
196
+ },
197
+ pressed: {
198
+ variants: { variant: {
199
+ primary: { opacity: PRESSED_FILL_OPACITY },
200
+ secondary: { opacity: PRESSED_FILL_OPACITY },
201
+ outline: {},
202
+ ghost: { backgroundColor: theme.colors.panel },
203
+ subtle: { backgroundColor: theme.colors.deep },
204
+ danger: { opacity: PRESSED_FILL_OPACITY },
205
+ "danger-outline": { opacity: PRESSED_FILL_OPACITY },
206
+ success: { opacity: PRESSED_FILL_OPACITY },
207
+ link: {}
208
+ } },
209
+ uni__dependencies: [0, 4]
210
+ },
211
+ disabled: { opacity: DISABLED_OPACITY },
212
+ label: {
213
+ fontFamily: fontOf(theme.fontFamily.sans),
214
+ fontWeight: theme.fontWeight.medium,
215
+ variants: {
216
+ variant: {
217
+ primary: { fontWeight: theme.fontWeight.semibold },
218
+ secondary: { fontWeight: theme.fontWeight.semibold },
219
+ outline: {},
220
+ ghost: {},
221
+ subtle: {},
222
+ danger: { fontWeight: theme.fontWeight.semibold },
223
+ "danger-outline": { fontWeight: theme.fontWeight.semibold },
224
+ success: { fontWeight: theme.fontWeight.semibold },
225
+ link: {}
226
+ },
227
+ size: {
228
+ xs: {
229
+ fontSize: theme.fontSize.sm,
230
+ lineHeight: theme.lineHeight.sm
231
+ },
232
+ sm: {
233
+ fontSize: theme.fontSize.sm,
234
+ lineHeight: theme.lineHeight.sm
235
+ },
236
+ md: {
237
+ fontSize: theme.fontSize.base,
238
+ lineHeight: theme.lineHeight.base
239
+ },
240
+ lg: {
241
+ fontSize: theme.fontSize.base,
242
+ lineHeight: theme.lineHeight.base
243
+ },
244
+ icon: {
245
+ fontSize: theme.fontSize.base,
246
+ lineHeight: theme.lineHeight.base
247
+ },
248
+ "icon-md": {
249
+ fontSize: theme.fontSize.base,
250
+ lineHeight: theme.lineHeight.base
251
+ },
252
+ card: {
253
+ fontSize: theme.fontSize.base,
254
+ lineHeight: theme.lineHeight.base
255
+ }
256
+ }
257
+ },
258
+ uni__dependencies: [0, 4]
259
+ },
260
+ labelPressed: {
261
+ variants: { variant: {
262
+ primary: {},
263
+ secondary: {},
264
+ outline: {},
265
+ ghost: {},
266
+ subtle: {},
267
+ danger: {},
268
+ "danger-outline": {},
269
+ success: {},
270
+ link: { textDecorationLine: "underline" }
271
+ } },
272
+ uni__dependencies: [4]
273
+ }
274
+ }));
275
+
276
+ //#endregion
277
+ export { Button };
278
+ //# sourceMappingURL=Button.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.mjs","names":["NativeColorToken","withAlpha","ReactNode","PressableProps","StyleProp","ViewStyle","StyleSheet","useUnistyles","IconColorContext","fontOf","impactLight","wrapText","Spinner","ButtonVariant","ButtonSize","MIN_TAP_TARGET","DISABLED_OPACITY","PRESSED_FILL_OPACITY","RIPPLE_ALPHA_PERCENT","PRESSED_EDGE_ALPHA_PERCENT","SIZE_HEIGHT","Readonly","Record","xs","sm","md","lg","icon","card","INK","rest","pressed","primary","secondary","outline","ghost","subtle","danger","success","link","HAPTIC_VARIANTS","ReadonlySet","Set","ButtonProps","Omit","variant","size","loading","loadingLabel","children","style","Button","disabled","onPress","hitSlop","accessibilityState","props","theme","_styles","styles","useVariants","inactive","slop","Math","max","ink","busy","undefined","text","color","colors","borderless","event","has","button","borderColor","green","token","label","labelPressed","create","flexDirection","alignItems","justifyContent","gap","spacing","borderRadius","borderWidth","overflow","variants","backgroundColor","selected","border","panel","red","height","paddingHorizontal","DEFAULT","width","padding","alignSelf","minHeight","paddingVertical","uni__dependencies","opacity","deep","fontFamily","sans","fontWeight","medium","semibold","fontSize","lineHeight","base","textDecorationLine"],"sources":["../../src/components/Button.tsx"],"sourcesContent":["import { type NativeColorToken, withAlpha } from '@agimon-ai/po-web-components/nativeTheme';\nimport type { ReactNode } from 'react';\nimport { Pressable, type PressableProps, type StyleProp, type ViewStyle } from 'react-native';\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\n\nimport { IconColorContext } from '../icons/IconColorContext';\nimport { fontOf } from '../lib/fonts';\nimport { impactLight } from '../lib/haptics';\nimport { wrapText } from '../lib/wrapText';\nimport { Spinner } from './Spinner';\n\nexport type ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'outline'\n | 'ghost'\n | 'subtle'\n | 'danger'\n | 'danger-outline'\n | 'success'\n | 'link';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'icon' | 'icon-md' | 'card';\n\n/** Apple's and Google's minimum tap target; a smaller visual box makes up the rest with hitSlop. */\nconst MIN_TAP_TARGET = 44;\nconst DISABLED_OPACITY = 0.4;\nconst PRESSED_FILL_OPACITY = 0.85;\nconst RIPPLE_ALPHA_PERCENT = 20;\n/** `hover:border-doom-green/50`. */\nconst PRESSED_EDGE_ALPHA_PERCENT = 50;\n\n/** The visual height of each size, from which hitSlop pads the tap target to 44pt. */\nconst SIZE_HEIGHT: Readonly<Record<ButtonSize, number>> = {\n xs: 24,\n sm: 28,\n md: 32,\n lg: 36,\n icon: 24,\n 'icon-md': 32,\n card: MIN_TAP_TARGET,\n};\n\n/** The label ink of each variant, and the ink it lifts to while pressed (the web hover). */\nconst INK: Readonly<Record<ButtonVariant, { rest: NativeColorToken; pressed: NativeColorToken }>> = {\n primary: { rest: 'on-selected', pressed: 'on-selected' },\n secondary: { rest: 'magenta', pressed: 'magenta' },\n outline: { rest: 'dim', pressed: 'hi' },\n ghost: { rest: 'dim', pressed: 'hi' },\n subtle: { rest: 'dim', pressed: 'hi' },\n danger: { rest: 'rail', pressed: 'rail' },\n 'danger-outline': { rest: 'red', pressed: 'red' },\n success: { rest: 'rail', pressed: 'rail' },\n link: { rest: 'blue', pressed: 'blue' },\n};\n\n/** Presses that commit something get a light impact; the rest stay quiet. */\nconst HAPTIC_VARIANTS: ReadonlySet<ButtonVariant> = new Set(['primary', 'danger', 'success']);\n\nexport interface ButtonProps extends Omit<PressableProps, 'children' | 'style'> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** Work is in flight: the button shows a spinner and stops accepting presses. */\n loading?: boolean;\n /** What the spinner announces while loading; omit it and the wait is silent. */\n loadingLabel?: string;\n /** A bare string is drawn as the label; elements (an icon, a card's lines) render as given. */\n children?: ReactNode;\n style?: StyleProp<ViewStyle>;\n}\n\n/** The one button: every variant is a theme token, a press dims or lifts it, and committing presses buzz once. */\nexport function Button({\n variant = 'outline',\n size = 'md',\n loading = false,\n loadingLabel,\n disabled,\n onPress,\n children,\n style,\n hitSlop,\n accessibilityState,\n ...props\n}: ButtonProps) {\n const { theme } = useUnistyles();\n styles.useVariants({ variant, size });\n const inactive = (disabled ?? false) || loading;\n const slop = Math.max(0, (MIN_TAP_TARGET - SIZE_HEIGHT[size]) / 2);\n const ink = INK[variant];\n return (\n <Pressable\n accessibilityRole={variant === 'link' ? 'link' : 'button'}\n accessibilityState={{ ...accessibilityState, disabled: inactive, busy: loading }}\n accessibilityValue={loading && loadingLabel !== undefined ? { text: loadingLabel } : undefined}\n disabled={inactive}\n hitSlop={hitSlop ?? slop}\n android_ripple={{ color: withAlpha(theme.colors[ink.pressed], RIPPLE_ALPHA_PERCENT), borderless: false }}\n onPress={(event) => {\n if (HAPTIC_VARIANTS.has(variant)) impactLight();\n onPress?.(event);\n }}\n style={({ pressed }) => [\n styles.button,\n pressed && styles.pressed,\n // Alpha mixes are computed in render from useUnistyles(), not in StyleSheet.create: on web Unistyles hands\n // the stylesheet CSS variables, which withAlpha cannot read.\n pressed && variant === 'outline' && { borderColor: withAlpha(theme.colors.green, PRESSED_EDGE_ALPHA_PERCENT) },\n inactive && styles.disabled,\n style,\n ]}\n {...props}\n >\n {({ pressed }) => {\n const token = pressed ? ink.pressed : ink.rest;\n return (\n <IconColorContext.Provider value={token}>\n {loading ? <Spinner color={token} /> : null}\n {wrapText(children, [styles.label, pressed && styles.labelPressed, { color: theme.colors[token] }])}\n </IconColorContext.Provider>\n );\n }}\n </Pressable>\n );\n}\n\nconst styles = StyleSheet.create((theme) => ({\n button: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.spacing(1.5),\n borderRadius: theme.borderRadius.md,\n borderWidth: 1,\n borderColor: 'transparent',\n overflow: 'hidden',\n variants: {\n variant: {\n primary: { backgroundColor: theme.colors.selected },\n secondary: { borderColor: theme.colors['edge-magenta'], backgroundColor: theme.colors['tint-magenta'] },\n outline: { borderColor: theme.colors.border },\n ghost: {},\n subtle: { backgroundColor: theme.colors.panel },\n danger: { backgroundColor: theme.colors.red },\n 'danger-outline': { borderColor: theme.colors['edge-red'], backgroundColor: theme.colors['tint-red'] },\n success: { backgroundColor: theme.colors.green },\n link: {},\n },\n size: {\n xs: { height: SIZE_HEIGHT.xs, paddingHorizontal: theme.spacing(1.5), borderRadius: theme.borderRadius.DEFAULT },\n sm: { height: SIZE_HEIGHT.sm, paddingHorizontal: theme.spacing(2.5) },\n md: { height: SIZE_HEIGHT.md, paddingHorizontal: theme.spacing(3) },\n lg: { height: SIZE_HEIGHT.lg, paddingHorizontal: theme.spacing(3.5) },\n icon: {\n width: SIZE_HEIGHT.icon,\n height: SIZE_HEIGHT.icon,\n padding: 0,\n borderRadius: theme.borderRadius.DEFAULT,\n },\n 'icon-md': { width: SIZE_HEIGHT['icon-md'], height: SIZE_HEIGHT['icon-md'], padding: 0 },\n card: {\n alignSelf: 'stretch',\n flexDirection: 'column',\n alignItems: 'stretch',\n justifyContent: 'flex-start',\n gap: theme.spacing(1),\n minHeight: SIZE_HEIGHT.card,\n paddingHorizontal: 11,\n paddingVertical: theme.spacing(2.5),\n },\n },\n },\n },\n pressed: {\n variants: {\n variant: {\n primary: { opacity: PRESSED_FILL_OPACITY },\n secondary: { opacity: PRESSED_FILL_OPACITY },\n outline: {},\n ghost: { backgroundColor: theme.colors.panel },\n subtle: { backgroundColor: theme.colors.deep },\n danger: { opacity: PRESSED_FILL_OPACITY },\n 'danger-outline': { opacity: PRESSED_FILL_OPACITY },\n success: { opacity: PRESSED_FILL_OPACITY },\n link: {},\n },\n },\n },\n disabled: { opacity: DISABLED_OPACITY },\n label: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontWeight: theme.fontWeight.medium,\n variants: {\n variant: {\n primary: { fontWeight: theme.fontWeight.semibold },\n secondary: { fontWeight: theme.fontWeight.semibold },\n outline: {},\n ghost: {},\n subtle: {},\n danger: { fontWeight: theme.fontWeight.semibold },\n 'danger-outline': { fontWeight: theme.fontWeight.semibold },\n success: { fontWeight: theme.fontWeight.semibold },\n link: {},\n },\n size: {\n xs: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm },\n sm: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm },\n md: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n lg: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n icon: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n 'icon-md': { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n card: { fontSize: theme.fontSize.base, lineHeight: theme.lineHeight.base },\n },\n },\n },\n labelPressed: {\n variants: {\n variant: {\n primary: {},\n secondary: {},\n outline: {},\n ghost: {},\n subtle: {},\n danger: {},\n 'danger-outline': {},\n success: {},\n link: { textDecorationLine: 'underline' },\n },\n },\n },\n}));\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ //#region src/components/CodeBlock.d.ts
2
+ export interface CodeBlockProps {
3
+ /** The block's source, without the fence lines. */
4
+ text: string;
5
+ /** The fence's language word, such as `ts`; the web reads it from a `language-*` class. */
6
+ language?: string;
7
+ }
8
+ export declare function CodeBlock({ text, language }: CodeBlockProps): import("react").JSX.Element;
9
+ //#endregion
10
+ //# sourceMappingURL=CodeBlock.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeBlock.d.mts","names":[],"sources":["../../src/components/CodeBlock.tsx"],"mappings":";iBA4BiB;;EAEf;;EAEA;;wBAGc,YAAY,MAAM,YAAY,iCAAc,IAAA"}