@scripso-homepad/ui 0.3.0 → 0.3.2

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 CHANGED
@@ -115,6 +115,8 @@ export function Example() {
115
115
 
116
116
  #### Tailwind classes (React web)
117
117
 
118
+ On web, `className` is applied to real DOM elements (`<button>` / `<span>`), so Tailwind utilities work with Vite or Next.js:
119
+
118
120
  ```tsx
119
121
  <Button
120
122
  title="Save"
@@ -124,7 +126,7 @@ export function Example() {
124
126
  />
125
127
  ```
126
128
 
127
- Default package styles are merged with your `style` / `className` values.
129
+ > **Note:** `react-native-web` does not forward `className` to the DOM by default. This package renders native HTML elements on web so Tailwind classes appear in the DOM. On React Native, use `style` or [NativeWind](https://www.nativewind.dev/) with `cssInterop`.
128
130
 
129
131
  ## Development
130
132
 
@@ -153,7 +155,7 @@ npm run build-storybook
153
155
 
154
156
  ## Publishing
155
157
 
156
- See [PUBLISHING.md](./PUBLISHING.md) for release workflow details.
158
+ Push to `main` — CI auto-bumps the patch version and publishes to npm. See [PUBLISHING.md](./PUBLISHING.md).
157
159
 
158
160
  ## Architecture
159
161
 
package/dist/index.cjs CHANGED
@@ -1,9 +1,42 @@
1
1
  'use strict';
2
2
 
3
+ var react = require('react');
3
4
  var reactNative = require('react-native');
4
5
  var jsxRuntime = require('react/jsx-runtime');
5
6
 
6
7
  // src/components/Button.tsx
8
+ function rnStyleToWebStyle(style) {
9
+ const flat = reactNative.StyleSheet.flatten(style);
10
+ if (!flat) return {};
11
+ const css = {};
12
+ for (const [key, value] of Object.entries(flat)) {
13
+ if (value === void 0 || value === null) continue;
14
+ switch (key) {
15
+ case "paddingVertical":
16
+ css.paddingTop = value;
17
+ css.paddingBottom = value;
18
+ break;
19
+ case "paddingHorizontal":
20
+ css.paddingLeft = value;
21
+ css.paddingRight = value;
22
+ break;
23
+ case "marginVertical":
24
+ css.marginTop = value;
25
+ css.marginBottom = value;
26
+ break;
27
+ case "marginHorizontal":
28
+ css.marginLeft = value;
29
+ css.marginRight = value;
30
+ break;
31
+ default:
32
+ css[key] = value;
33
+ }
34
+ }
35
+ if (css.alignItems || css.justifyContent || css.flexDirection) {
36
+ css.display = css.display ?? "flex";
37
+ }
38
+ return css;
39
+ }
7
40
  function Button({
8
41
  title,
9
42
  onPress,
@@ -13,26 +46,42 @@ function Button({
13
46
  className,
14
47
  textClassName
15
48
  }) {
16
- const containerWebProps = className != null ? { className } : {};
17
- const textWebProps = textClassName != null ? { className: textClassName } : {};
49
+ const containerStyle = [styles.button, disabled && styles.buttonDisabled, style];
50
+ const labelStyle = [styles.text, disabled && styles.textDisabled, textStyle];
51
+ const useWebDom = reactNative.Platform.OS === "web" && (className != null || textClassName != null);
52
+ if (useWebDom) {
53
+ return react.createElement(
54
+ "button",
55
+ {
56
+ type: "button",
57
+ className,
58
+ style: rnStyleToWebStyle(containerStyle),
59
+ disabled,
60
+ onClick: (event) => {
61
+ onPress(event);
62
+ },
63
+ "aria-disabled": disabled
64
+ },
65
+ react.createElement(
66
+ "span",
67
+ {
68
+ className: textClassName,
69
+ style: rnStyleToWebStyle(labelStyle)
70
+ },
71
+ title
72
+ )
73
+ );
74
+ }
18
75
  return /* @__PURE__ */ jsxRuntime.jsx(
19
76
  reactNative.TouchableOpacity,
20
77
  {
21
- style: [styles.button, disabled && styles.buttonDisabled, style],
78
+ style: containerStyle,
22
79
  onPress,
23
80
  disabled,
24
81
  activeOpacity: 0.7,
25
82
  accessibilityRole: "button",
26
83
  accessibilityState: { disabled },
27
- ...containerWebProps,
28
- children: /* @__PURE__ */ jsxRuntime.jsx(
29
- reactNative.Text,
30
- {
31
- style: [styles.text, disabled && styles.textDisabled, textStyle],
32
- ...textWebProps,
33
- children: title
34
- }
35
- )
84
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: labelStyle, children: title })
36
85
  }
37
86
  );
38
87
  }
@@ -44,7 +93,8 @@ var styles = reactNative.StyleSheet.create({
44
93
  borderRadius: 8,
45
94
  alignItems: "center",
46
95
  justifyContent: "center",
47
- minWidth: 120
96
+ minWidth: 120,
97
+ borderWidth: 0
48
98
  },
49
99
  buttonDisabled: {
50
100
  backgroundColor: "#93c5fd",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Button.tsx"],"names":["jsx","TouchableOpacity","Text","StyleSheet"],"mappings":";;;;;;AA2BO,SAAS,MAAA,CAAO;AAAA,EACrB,KAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,KAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAAgB;AACd,EAAA,MAAM,oBACJ,SAAA,IAAa,IAAA,GAAQ,EAAE,SAAA,KAA0C,EAAC;AACpE,EAAA,MAAM,eACJ,aAAA,IAAiB,IAAA,GAAQ,EAAE,SAAA,EAAW,aAAA,KAA8C,EAAC;AAEvF,EAAA,uBACEA,cAAA;AAAA,IAACC,4BAAA;AAAA,IAAA;AAAA,MACC,OAAO,CAAC,MAAA,CAAO,QAAQ,QAAA,IAAY,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAAA,MAC/D,OAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAA,EAAe,GAAA;AAAA,MACf,iBAAA,EAAkB,QAAA;AAAA,MAClB,kBAAA,EAAoB,EAAE,QAAA,EAAS;AAAA,MAC9B,GAAG,iBAAA;AAAA,MAEJ,QAAA,kBAAAD,cAAA;AAAA,QAACE,gBAAA;AAAA,QAAA;AAAA,UACC,OAAO,CAAC,MAAA,CAAO,MAAM,QAAA,IAAY,MAAA,CAAO,cAAc,SAAS,CAAA;AAAA,UAC9D,GAAG,YAAA;AAAA,UAEH,QAAA,EAAA;AAAA;AAAA;AACH;AAAA,GACF;AAEJ;AAEA,IAAM,MAAA,GAASC,uBAAW,MAAA,CAAO;AAAA,EAC/B,MAAA,EAAQ;AAAA,IACN,eAAA,EAAiB,SAAA;AAAA,IACjB,eAAA,EAAiB,EAAA;AAAA,IACjB,iBAAA,EAAmB,EAAA;AAAA,IACnB,YAAA,EAAc,CAAA;AAAA,IACd,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,QAAA;AAAA,IAChB,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,cAAA,EAAgB;AAAA,IACd,eAAA,EAAiB,SAAA;AAAA,IACjB,OAAA,EAAS;AAAA,GACX;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,KAAA,EAAO,SAAA;AAAA,IACP,QAAA,EAAU,EAAA;AAAA,IACV,UAAA,EAAY;AAAA,GACd;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,KAAA,EAAO;AAAA;AAEX,CAAC,CAAA","file":"index.cjs","sourcesContent":["import {\n StyleSheet,\n Text,\n TouchableOpacity,\n type GestureResponderEvent,\n type StyleProp,\n type TextStyle,\n type ViewStyle,\n} from \"react-native\";\n\nexport interface ButtonProps {\n title: string;\n onPress: (event: GestureResponderEvent) => void;\n disabled?: boolean;\n /** Additional container styles (works on web and native). */\n style?: StyleProp<ViewStyle>;\n /** Additional label styles (works on web and native). */\n textStyle?: StyleProp<TextStyle>;\n /**\n * CSS class names for the container (web via react-native-web, or native with NativeWind).\n * Merged with default styles use Tailwind utilities in React web apps.\n */\n className?: string;\n /** CSS class names for the label (web via react-native-web, or native with NativeWind). */\n textClassName?: string;\n}\n\nexport function Button({\n title,\n onPress,\n disabled = false,\n style,\n textStyle,\n className,\n textClassName,\n}: ButtonProps) {\n const containerWebProps =\n className != null ? ({ className } as Record<string, unknown>) : {};\n const textWebProps =\n textClassName != null ? ({ className: textClassName } as Record<string, unknown>) : {};\n\n return (\n <TouchableOpacity\n style={[styles.button, disabled && styles.buttonDisabled, style]}\n onPress={onPress}\n disabled={disabled}\n activeOpacity={0.7}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled }}\n {...containerWebProps}\n >\n <Text\n style={[styles.text, disabled && styles.textDisabled, textStyle]}\n {...textWebProps}\n >\n {title}\n </Text>\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n button: {\n backgroundColor: \"#2563eb\",\n paddingVertical: 12,\n paddingHorizontal: 24,\n borderRadius: 8,\n alignItems: \"center\",\n justifyContent: \"center\",\n minWidth: 120,\n },\n buttonDisabled: {\n backgroundColor: \"#93c5fd\",\n opacity: 0.7,\n },\n text: {\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n textDisabled: {\n color: \"#e5e7eb\",\n },\n});\n"]}
1
+ {"version":3,"sources":["../src/utils/rnStyleToWebStyle.ts","../src/components/Button.tsx"],"names":["StyleSheet","Platform","createElement","jsx","TouchableOpacity","Text"],"mappings":";;;;;;;AASO,SAAS,kBAAkB,KAAA,EAA+B;AAC/D,EAAA,MAAM,IAAA,GAAOA,sBAAA,CAAW,OAAA,CAAQ,KAAK,CAAA;AACrC,EAAA,IAAI,CAAC,IAAA,EAAM,OAAO,EAAC;AAEnB,EAAA,MAAM,MAA+B,EAAC;AAEtC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AAE3C,IAAA,QAAQ,GAAA;AAAK,MACX,KAAK,iBAAA;AACH,QAAA,GAAA,CAAI,UAAA,GAAa,KAAA;AACjB,QAAA,GAAA,CAAI,aAAA,GAAgB,KAAA;AACpB,QAAA;AAAA,MACF,KAAK,mBAAA;AACH,QAAA,GAAA,CAAI,WAAA,GAAc,KAAA;AAClB,QAAA,GAAA,CAAI,YAAA,GAAe,KAAA;AACnB,QAAA;AAAA,MACF,KAAK,gBAAA;AACH,QAAA,GAAA,CAAI,SAAA,GAAY,KAAA;AAChB,QAAA,GAAA,CAAI,YAAA,GAAe,KAAA;AACnB,QAAA;AAAA,MACF,KAAK,kBAAA;AACH,QAAA,GAAA,CAAI,UAAA,GAAa,KAAA;AACjB,QAAA,GAAA,CAAI,WAAA,GAAc,KAAA;AAClB,QAAA;AAAA,MACF;AACE,QAAA,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAAA;AACf,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,UAAA,IAAc,GAAA,CAAI,cAAA,IAAkB,IAAI,aAAA,EAAe;AAC7D,IAAA,GAAA,CAAI,OAAA,GAAU,IAAI,OAAA,IAAW,MAAA;AAAA,EAC/B;AAEA,EAAA,OAAO,GAAA;AACT;ACZO,SAAS,MAAA,CAAO;AAAA,EACrB,KAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,KAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAAgB;AACd,EAAA,MAAM,iBAAiB,CAAC,MAAA,CAAO,QAAQ,QAAA,IAAY,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAC/E,EAAA,MAAM,aAAa,CAAC,MAAA,CAAO,MAAM,QAAA,IAAY,MAAA,CAAO,cAAc,SAAS,CAAA;AAE3E,EAAA,MAAM,YACJC,oBAAA,CAAS,EAAA,KAAO,KAAA,KAAU,SAAA,IAAa,QAAQ,aAAA,IAAiB,IAAA,CAAA;AAElE,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,OAAOC,mBAAA;AAAA,MACL,QAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,SAAA;AAAA,QACA,KAAA,EAAO,kBAAkB,cAAc,CAAA;AAAA,QACvC,QAAA;AAAA,QACA,OAAA,EAAS,CAAC,KAAA,KAA+C;AACvD,UAAA,OAAA,CAAQ,KAAyC,CAAA;AAAA,QACnD,CAAA;AAAA,QACA,eAAA,EAAiB;AAAA,OACnB;AAAA,MACAA,mBAAA;AAAA,QACE,MAAA;AAAA,QACA;AAAA,UACE,SAAA,EAAW,aAAA;AAAA,UACX,KAAA,EAAO,kBAAkB,UAAU;AAAA,SACrC;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF;AAEA,EAAA,uBACEC,cAAA;AAAA,IAACC,4BAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,cAAA;AAAA,MACP,OAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAA,EAAe,GAAA;AAAA,MACf,iBAAA,EAAkB,QAAA;AAAA,MAClB,kBAAA,EAAoB,EAAE,QAAA,EAAS;AAAA,MAE/B,QAAA,kBAAAD,cAAA,CAACE,gBAAA,EAAA,EAAK,KAAA,EAAO,UAAA,EAAa,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA,GAClC;AAEJ;AAEA,IAAM,MAAA,GAASL,uBAAW,MAAA,CAAO;AAAA,EAC/B,MAAA,EAAQ;AAAA,IACN,eAAA,EAAiB,SAAA;AAAA,IACjB,eAAA,EAAiB,EAAA;AAAA,IACjB,iBAAA,EAAmB,EAAA;AAAA,IACnB,YAAA,EAAc,CAAA;AAAA,IACd,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,QAAA;AAAA,IAChB,QAAA,EAAU,GAAA;AAAA,IACV,WAAA,EAAa;AAAA,GACf;AAAA,EACA,cAAA,EAAgB;AAAA,IACd,eAAA,EAAiB,SAAA;AAAA,IACjB,OAAA,EAAS;AAAA,GACX;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,KAAA,EAAO,SAAA;AAAA,IACP,QAAA,EAAU,EAAA;AAAA,IACV,UAAA,EAAY;AAAA,GACd;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,KAAA,EAAO;AAAA;AAEX,CAAC,CAAA","file":"index.cjs","sourcesContent":["import { StyleSheet, type StyleProp, type TextStyle, type ViewStyle } from \"react-native\";\nimport type { CSSProperties } from \"react\";\n\ntype RNStyle = StyleProp<ViewStyle> | StyleProp<TextStyle>;\n\n/**\n * Converts React Native StyleSheet values to CSS properties for DOM elements.\n * Required when rendering native HTML on web (browsers ignore paddingVertical, etc.).\n */\nexport function rnStyleToWebStyle(style: RNStyle): CSSProperties {\n const flat = StyleSheet.flatten(style);\n if (!flat) return {};\n\n const css: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(flat)) {\n if (value === undefined || value === null) continue;\n\n switch (key) {\n case \"paddingVertical\":\n css.paddingTop = value;\n css.paddingBottom = value;\n break;\n case \"paddingHorizontal\":\n css.paddingLeft = value;\n css.paddingRight = value;\n break;\n case \"marginVertical\":\n css.marginTop = value;\n css.marginBottom = value;\n break;\n case \"marginHorizontal\":\n css.marginLeft = value;\n css.marginRight = value;\n break;\n default:\n css[key] = value;\n }\n }\n\n if (css.alignItems || css.justifyContent || css.flexDirection) {\n css.display = css.display ?? \"flex\";\n }\n\n return css as CSSProperties;\n}\n","import React, { createElement } from \"react\";\nimport {\n Platform,\n StyleSheet,\n Text,\n TouchableOpacity,\n type GestureResponderEvent,\n type StyleProp,\n type TextStyle,\n type ViewStyle,\n} from \"react-native\";\nimport { rnStyleToWebStyle } from \"../utils/rnStyleToWebStyle\";\n\nexport interface ButtonProps {\n title: string;\n onPress: (event: GestureResponderEvent) => void;\n disabled?: boolean;\n /** Additional container styles (works on web and native). */\n style?: StyleProp<ViewStyle>;\n /** Additional label styles (works on web and native). */\n textStyle?: StyleProp<TextStyle>;\n /**\n * CSS class names for the container (web only uses DOM `<button>` for Tailwind).\n * On native: ignored unless using NativeWind with cssInterop.\n */\n className?: string;\n /**\n * CSS class names for the label (web only).\n * On native: ignored unless using NativeWind with cssInterop.\n */\n textClassName?: string;\n}\n\nexport function Button({\n title,\n onPress,\n disabled = false,\n style,\n textStyle,\n className,\n textClassName,\n}: ButtonProps) {\n const containerStyle = [styles.button, disabled && styles.buttonDisabled, style];\n const labelStyle = [styles.text, disabled && styles.textDisabled, textStyle];\n\n const useWebDom =\n Platform.OS === \"web\" && (className != null || textClassName != null);\n\n if (useWebDom) {\n return createElement(\n \"button\",\n {\n type: \"button\",\n className,\n style: rnStyleToWebStyle(containerStyle),\n disabled,\n onClick: (event: React.MouseEvent<HTMLButtonElement>) => {\n onPress(event as unknown as GestureResponderEvent);\n },\n \"aria-disabled\": disabled,\n },\n createElement(\n \"span\",\n {\n className: textClassName,\n style: rnStyleToWebStyle(labelStyle),\n },\n title,\n ),\n );\n }\n\n return (\n <TouchableOpacity\n style={containerStyle}\n onPress={onPress}\n disabled={disabled}\n activeOpacity={0.7}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled }}\n >\n <Text style={labelStyle}>{title}</Text>\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n button: {\n backgroundColor: \"#2563eb\",\n paddingVertical: 12,\n paddingHorizontal: 24,\n borderRadius: 8,\n alignItems: \"center\",\n justifyContent: \"center\",\n minWidth: 120,\n borderWidth: 0,\n },\n buttonDisabled: {\n backgroundColor: \"#93c5fd\",\n opacity: 0.7,\n },\n text: {\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n textDisabled: {\n color: \"#e5e7eb\",\n },\n});\n"]}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react from 'react';
1
+ import React from 'react';
2
2
  import { GestureResponderEvent, StyleProp, ViewStyle, TextStyle } from 'react-native';
3
3
 
4
4
  interface ButtonProps {
@@ -10,13 +10,16 @@ interface ButtonProps {
10
10
  /** Additional label styles (works on web and native). */
11
11
  textStyle?: StyleProp<TextStyle>;
12
12
  /**
13
- * CSS class names for the container (web via react-native-web, or native with NativeWind).
14
- * Merged with default styles use Tailwind utilities in React web apps.
13
+ * CSS class names for the container (web only uses DOM `<button>` for Tailwind).
14
+ * On native: ignored unless using NativeWind with cssInterop.
15
15
  */
16
16
  className?: string;
17
- /** CSS class names for the label (web via react-native-web, or native with NativeWind). */
17
+ /**
18
+ * CSS class names for the label (web only).
19
+ * On native: ignored unless using NativeWind with cssInterop.
20
+ */
18
21
  textClassName?: string;
19
22
  }
20
- declare function Button({ title, onPress, disabled, style, textStyle, className, textClassName, }: ButtonProps): react.JSX.Element;
23
+ declare function Button({ title, onPress, disabled, style, textStyle, className, textClassName, }: ButtonProps): React.JSX.Element;
21
24
 
22
25
  export { Button, type ButtonProps };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react from 'react';
1
+ import React from 'react';
2
2
  import { GestureResponderEvent, StyleProp, ViewStyle, TextStyle } from 'react-native';
3
3
 
4
4
  interface ButtonProps {
@@ -10,13 +10,16 @@ interface ButtonProps {
10
10
  /** Additional label styles (works on web and native). */
11
11
  textStyle?: StyleProp<TextStyle>;
12
12
  /**
13
- * CSS class names for the container (web via react-native-web, or native with NativeWind).
14
- * Merged with default styles use Tailwind utilities in React web apps.
13
+ * CSS class names for the container (web only uses DOM `<button>` for Tailwind).
14
+ * On native: ignored unless using NativeWind with cssInterop.
15
15
  */
16
16
  className?: string;
17
- /** CSS class names for the label (web via react-native-web, or native with NativeWind). */
17
+ /**
18
+ * CSS class names for the label (web only).
19
+ * On native: ignored unless using NativeWind with cssInterop.
20
+ */
18
21
  textClassName?: string;
19
22
  }
20
- declare function Button({ title, onPress, disabled, style, textStyle, className, textClassName, }: ButtonProps): react.JSX.Element;
23
+ declare function Button({ title, onPress, disabled, style, textStyle, className, textClassName, }: ButtonProps): React.JSX.Element;
21
24
 
22
25
  export { Button, type ButtonProps };
package/dist/index.js CHANGED
@@ -1,7 +1,40 @@
1
- import { StyleSheet, TouchableOpacity, Text } from 'react-native';
1
+ import { createElement } from 'react';
2
+ import { StyleSheet, Platform, TouchableOpacity, Text } from 'react-native';
2
3
  import { jsx } from 'react/jsx-runtime';
3
4
 
4
5
  // src/components/Button.tsx
6
+ function rnStyleToWebStyle(style) {
7
+ const flat = StyleSheet.flatten(style);
8
+ if (!flat) return {};
9
+ const css = {};
10
+ for (const [key, value] of Object.entries(flat)) {
11
+ if (value === void 0 || value === null) continue;
12
+ switch (key) {
13
+ case "paddingVertical":
14
+ css.paddingTop = value;
15
+ css.paddingBottom = value;
16
+ break;
17
+ case "paddingHorizontal":
18
+ css.paddingLeft = value;
19
+ css.paddingRight = value;
20
+ break;
21
+ case "marginVertical":
22
+ css.marginTop = value;
23
+ css.marginBottom = value;
24
+ break;
25
+ case "marginHorizontal":
26
+ css.marginLeft = value;
27
+ css.marginRight = value;
28
+ break;
29
+ default:
30
+ css[key] = value;
31
+ }
32
+ }
33
+ if (css.alignItems || css.justifyContent || css.flexDirection) {
34
+ css.display = css.display ?? "flex";
35
+ }
36
+ return css;
37
+ }
5
38
  function Button({
6
39
  title,
7
40
  onPress,
@@ -11,26 +44,42 @@ function Button({
11
44
  className,
12
45
  textClassName
13
46
  }) {
14
- const containerWebProps = className != null ? { className } : {};
15
- const textWebProps = textClassName != null ? { className: textClassName } : {};
47
+ const containerStyle = [styles.button, disabled && styles.buttonDisabled, style];
48
+ const labelStyle = [styles.text, disabled && styles.textDisabled, textStyle];
49
+ const useWebDom = Platform.OS === "web" && (className != null || textClassName != null);
50
+ if (useWebDom) {
51
+ return createElement(
52
+ "button",
53
+ {
54
+ type: "button",
55
+ className,
56
+ style: rnStyleToWebStyle(containerStyle),
57
+ disabled,
58
+ onClick: (event) => {
59
+ onPress(event);
60
+ },
61
+ "aria-disabled": disabled
62
+ },
63
+ createElement(
64
+ "span",
65
+ {
66
+ className: textClassName,
67
+ style: rnStyleToWebStyle(labelStyle)
68
+ },
69
+ title
70
+ )
71
+ );
72
+ }
16
73
  return /* @__PURE__ */ jsx(
17
74
  TouchableOpacity,
18
75
  {
19
- style: [styles.button, disabled && styles.buttonDisabled, style],
76
+ style: containerStyle,
20
77
  onPress,
21
78
  disabled,
22
79
  activeOpacity: 0.7,
23
80
  accessibilityRole: "button",
24
81
  accessibilityState: { disabled },
25
- ...containerWebProps,
26
- children: /* @__PURE__ */ jsx(
27
- Text,
28
- {
29
- style: [styles.text, disabled && styles.textDisabled, textStyle],
30
- ...textWebProps,
31
- children: title
32
- }
33
- )
82
+ children: /* @__PURE__ */ jsx(Text, { style: labelStyle, children: title })
34
83
  }
35
84
  );
36
85
  }
@@ -42,7 +91,8 @@ var styles = StyleSheet.create({
42
91
  borderRadius: 8,
43
92
  alignItems: "center",
44
93
  justifyContent: "center",
45
- minWidth: 120
94
+ minWidth: 120,
95
+ borderWidth: 0
46
96
  },
47
97
  buttonDisabled: {
48
98
  backgroundColor: "#93c5fd",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Button.tsx"],"names":[],"mappings":";;;;AA2BO,SAAS,MAAA,CAAO;AAAA,EACrB,KAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,KAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAAgB;AACd,EAAA,MAAM,oBACJ,SAAA,IAAa,IAAA,GAAQ,EAAE,SAAA,KAA0C,EAAC;AACpE,EAAA,MAAM,eACJ,aAAA,IAAiB,IAAA,GAAQ,EAAE,SAAA,EAAW,aAAA,KAA8C,EAAC;AAEvF,EAAA,uBACE,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,OAAO,CAAC,MAAA,CAAO,QAAQ,QAAA,IAAY,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAAA,MAC/D,OAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAA,EAAe,GAAA;AAAA,MACf,iBAAA,EAAkB,QAAA;AAAA,MAClB,kBAAA,EAAoB,EAAE,QAAA,EAAS;AAAA,MAC9B,GAAG,iBAAA;AAAA,MAEJ,QAAA,kBAAA,GAAA;AAAA,QAAC,IAAA;AAAA,QAAA;AAAA,UACC,OAAO,CAAC,MAAA,CAAO,MAAM,QAAA,IAAY,MAAA,CAAO,cAAc,SAAS,CAAA;AAAA,UAC9D,GAAG,YAAA;AAAA,UAEH,QAAA,EAAA;AAAA;AAAA;AACH;AAAA,GACF;AAEJ;AAEA,IAAM,MAAA,GAAS,WAAW,MAAA,CAAO;AAAA,EAC/B,MAAA,EAAQ;AAAA,IACN,eAAA,EAAiB,SAAA;AAAA,IACjB,eAAA,EAAiB,EAAA;AAAA,IACjB,iBAAA,EAAmB,EAAA;AAAA,IACnB,YAAA,EAAc,CAAA;AAAA,IACd,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,QAAA;AAAA,IAChB,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,cAAA,EAAgB;AAAA,IACd,eAAA,EAAiB,SAAA;AAAA,IACjB,OAAA,EAAS;AAAA,GACX;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,KAAA,EAAO,SAAA;AAAA,IACP,QAAA,EAAU,EAAA;AAAA,IACV,UAAA,EAAY;AAAA,GACd;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,KAAA,EAAO;AAAA;AAEX,CAAC,CAAA","file":"index.js","sourcesContent":["import {\n StyleSheet,\n Text,\n TouchableOpacity,\n type GestureResponderEvent,\n type StyleProp,\n type TextStyle,\n type ViewStyle,\n} from \"react-native\";\n\nexport interface ButtonProps {\n title: string;\n onPress: (event: GestureResponderEvent) => void;\n disabled?: boolean;\n /** Additional container styles (works on web and native). */\n style?: StyleProp<ViewStyle>;\n /** Additional label styles (works on web and native). */\n textStyle?: StyleProp<TextStyle>;\n /**\n * CSS class names for the container (web via react-native-web, or native with NativeWind).\n * Merged with default styles use Tailwind utilities in React web apps.\n */\n className?: string;\n /** CSS class names for the label (web via react-native-web, or native with NativeWind). */\n textClassName?: string;\n}\n\nexport function Button({\n title,\n onPress,\n disabled = false,\n style,\n textStyle,\n className,\n textClassName,\n}: ButtonProps) {\n const containerWebProps =\n className != null ? ({ className } as Record<string, unknown>) : {};\n const textWebProps =\n textClassName != null ? ({ className: textClassName } as Record<string, unknown>) : {};\n\n return (\n <TouchableOpacity\n style={[styles.button, disabled && styles.buttonDisabled, style]}\n onPress={onPress}\n disabled={disabled}\n activeOpacity={0.7}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled }}\n {...containerWebProps}\n >\n <Text\n style={[styles.text, disabled && styles.textDisabled, textStyle]}\n {...textWebProps}\n >\n {title}\n </Text>\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n button: {\n backgroundColor: \"#2563eb\",\n paddingVertical: 12,\n paddingHorizontal: 24,\n borderRadius: 8,\n alignItems: \"center\",\n justifyContent: \"center\",\n minWidth: 120,\n },\n buttonDisabled: {\n backgroundColor: \"#93c5fd\",\n opacity: 0.7,\n },\n text: {\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n textDisabled: {\n color: \"#e5e7eb\",\n },\n});\n"]}
1
+ {"version":3,"sources":["../src/utils/rnStyleToWebStyle.ts","../src/components/Button.tsx"],"names":["StyleSheet"],"mappings":"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","file":"index.js","sourcesContent":["import { StyleSheet, type StyleProp, type TextStyle, type ViewStyle } from \"react-native\";\nimport type { CSSProperties } from \"react\";\n\ntype RNStyle = StyleProp<ViewStyle> | StyleProp<TextStyle>;\n\n/**\n * Converts React Native StyleSheet values to CSS properties for DOM elements.\n * Required when rendering native HTML on web (browsers ignore paddingVertical, etc.).\n */\nexport function rnStyleToWebStyle(style: RNStyle): CSSProperties {\n const flat = StyleSheet.flatten(style);\n if (!flat) return {};\n\n const css: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(flat)) {\n if (value === undefined || value === null) continue;\n\n switch (key) {\n case \"paddingVertical\":\n css.paddingTop = value;\n css.paddingBottom = value;\n break;\n case \"paddingHorizontal\":\n css.paddingLeft = value;\n css.paddingRight = value;\n break;\n case \"marginVertical\":\n css.marginTop = value;\n css.marginBottom = value;\n break;\n case \"marginHorizontal\":\n css.marginLeft = value;\n css.marginRight = value;\n break;\n default:\n css[key] = value;\n }\n }\n\n if (css.alignItems || css.justifyContent || css.flexDirection) {\n css.display = css.display ?? \"flex\";\n }\n\n return css as CSSProperties;\n}\n","import React, { createElement } from \"react\";\nimport {\n Platform,\n StyleSheet,\n Text,\n TouchableOpacity,\n type GestureResponderEvent,\n type StyleProp,\n type TextStyle,\n type ViewStyle,\n} from \"react-native\";\nimport { rnStyleToWebStyle } from \"../utils/rnStyleToWebStyle\";\n\nexport interface ButtonProps {\n title: string;\n onPress: (event: GestureResponderEvent) => void;\n disabled?: boolean;\n /** Additional container styles (works on web and native). */\n style?: StyleProp<ViewStyle>;\n /** Additional label styles (works on web and native). */\n textStyle?: StyleProp<TextStyle>;\n /**\n * CSS class names for the container (web only uses DOM `<button>` for Tailwind).\n * On native: ignored unless using NativeWind with cssInterop.\n */\n className?: string;\n /**\n * CSS class names for the label (web only).\n * On native: ignored unless using NativeWind with cssInterop.\n */\n textClassName?: string;\n}\n\nexport function Button({\n title,\n onPress,\n disabled = false,\n style,\n textStyle,\n className,\n textClassName,\n}: ButtonProps) {\n const containerStyle = [styles.button, disabled && styles.buttonDisabled, style];\n const labelStyle = [styles.text, disabled && styles.textDisabled, textStyle];\n\n const useWebDom =\n Platform.OS === \"web\" && (className != null || textClassName != null);\n\n if (useWebDom) {\n return createElement(\n \"button\",\n {\n type: \"button\",\n className,\n style: rnStyleToWebStyle(containerStyle),\n disabled,\n onClick: (event: React.MouseEvent<HTMLButtonElement>) => {\n onPress(event as unknown as GestureResponderEvent);\n },\n \"aria-disabled\": disabled,\n },\n createElement(\n \"span\",\n {\n className: textClassName,\n style: rnStyleToWebStyle(labelStyle),\n },\n title,\n ),\n );\n }\n\n return (\n <TouchableOpacity\n style={containerStyle}\n onPress={onPress}\n disabled={disabled}\n activeOpacity={0.7}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled }}\n >\n <Text style={labelStyle}>{title}</Text>\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n button: {\n backgroundColor: \"#2563eb\",\n paddingVertical: 12,\n paddingHorizontal: 24,\n borderRadius: 8,\n alignItems: \"center\",\n justifyContent: \"center\",\n minWidth: 120,\n borderWidth: 0,\n },\n buttonDisabled: {\n backgroundColor: \"#93c5fd\",\n opacity: 0.7,\n },\n text: {\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: \"600\",\n },\n textDisabled: {\n color: \"#e5e7eb\",\n },\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scripso-homepad/ui",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "type": "module",
5
5
  "description": "Cross-platform UI components for Homepad (React Web + React Native)",
6
6
  "license": "MIT",
@@ -35,18 +35,13 @@
35
35
  "clean": "rm -rf dist",
36
36
  "storybook": "storybook dev -p 6006",
37
37
  "build-storybook": "storybook build",
38
- "prepublishOnly": "npm run build",
39
- "changeset": "changeset",
40
- "version-packages": "changeset version",
41
- "release": "npm run build && changeset publish"
38
+ "prepublishOnly": "npm run build"
42
39
  },
43
40
  "peerDependencies": {
44
41
  "react": ">=18",
45
42
  "react-native": ">=0.74"
46
43
  },
47
44
  "devDependencies": {
48
- "@changesets/changelog-github": "^0.5.0",
49
- "@changesets/cli": "^2.27.10",
50
45
  "@eslint/js": "^9.17.0",
51
46
  "@storybook/addon-essentials": "^8.4.7",
52
47
  "@storybook/addon-interactions": "^8.4.7",
@@ -1,4 +1,6 @@
1
+ import React, { createElement } from "react";
1
2
  import {
3
+ Platform,
2
4
  StyleSheet,
3
5
  Text,
4
6
  TouchableOpacity,
@@ -7,6 +9,7 @@ import {
7
9
  type TextStyle,
8
10
  type ViewStyle,
9
11
  } from "react-native";
12
+ import { rnStyleToWebStyle } from "../utils/rnStyleToWebStyle";
10
13
 
11
14
  export interface ButtonProps {
12
15
  title: string;
@@ -17,11 +20,14 @@ export interface ButtonProps {
17
20
  /** Additional label styles (works on web and native). */
18
21
  textStyle?: StyleProp<TextStyle>;
19
22
  /**
20
- * CSS class names for the container (web via react-native-web, or native with NativeWind).
21
- * Merged with default styles use Tailwind utilities in React web apps.
23
+ * CSS class names for the container (web only uses DOM `<button>` for Tailwind).
24
+ * On native: ignored unless using NativeWind with cssInterop.
22
25
  */
23
26
  className?: string;
24
- /** CSS class names for the label (web via react-native-web, or native with NativeWind). */
27
+ /**
28
+ * CSS class names for the label (web only).
29
+ * On native: ignored unless using NativeWind with cssInterop.
30
+ */
25
31
  textClassName?: string;
26
32
  }
27
33
 
@@ -34,27 +40,46 @@ export function Button({
34
40
  className,
35
41
  textClassName,
36
42
  }: ButtonProps) {
37
- const containerWebProps =
38
- className != null ? ({ className } as Record<string, unknown>) : {};
39
- const textWebProps =
40
- textClassName != null ? ({ className: textClassName } as Record<string, unknown>) : {};
43
+ const containerStyle = [styles.button, disabled && styles.buttonDisabled, style];
44
+ const labelStyle = [styles.text, disabled && styles.textDisabled, textStyle];
45
+
46
+ const useWebDom =
47
+ Platform.OS === "web" && (className != null || textClassName != null);
48
+
49
+ if (useWebDom) {
50
+ return createElement(
51
+ "button",
52
+ {
53
+ type: "button",
54
+ className,
55
+ style: rnStyleToWebStyle(containerStyle),
56
+ disabled,
57
+ onClick: (event: React.MouseEvent<HTMLButtonElement>) => {
58
+ onPress(event as unknown as GestureResponderEvent);
59
+ },
60
+ "aria-disabled": disabled,
61
+ },
62
+ createElement(
63
+ "span",
64
+ {
65
+ className: textClassName,
66
+ style: rnStyleToWebStyle(labelStyle),
67
+ },
68
+ title,
69
+ ),
70
+ );
71
+ }
41
72
 
42
73
  return (
43
74
  <TouchableOpacity
44
- style={[styles.button, disabled && styles.buttonDisabled, style]}
75
+ style={containerStyle}
45
76
  onPress={onPress}
46
77
  disabled={disabled}
47
78
  activeOpacity={0.7}
48
79
  accessibilityRole="button"
49
80
  accessibilityState={{ disabled }}
50
- {...containerWebProps}
51
81
  >
52
- <Text
53
- style={[styles.text, disabled && styles.textDisabled, textStyle]}
54
- {...textWebProps}
55
- >
56
- {title}
57
- </Text>
82
+ <Text style={labelStyle}>{title}</Text>
58
83
  </TouchableOpacity>
59
84
  );
60
85
  }
@@ -68,6 +93,7 @@ const styles = StyleSheet.create({
68
93
  alignItems: "center",
69
94
  justifyContent: "center",
70
95
  minWidth: 120,
96
+ borderWidth: 0,
71
97
  },
72
98
  buttonDisabled: {
73
99
  backgroundColor: "#93c5fd",
@@ -0,0 +1,46 @@
1
+ import { StyleSheet, type StyleProp, type TextStyle, type ViewStyle } from "react-native";
2
+ import type { CSSProperties } from "react";
3
+
4
+ type RNStyle = StyleProp<ViewStyle> | StyleProp<TextStyle>;
5
+
6
+ /**
7
+ * Converts React Native StyleSheet values to CSS properties for DOM elements.
8
+ * Required when rendering native HTML on web (browsers ignore paddingVertical, etc.).
9
+ */
10
+ export function rnStyleToWebStyle(style: RNStyle): CSSProperties {
11
+ const flat = StyleSheet.flatten(style);
12
+ if (!flat) return {};
13
+
14
+ const css: Record<string, unknown> = {};
15
+
16
+ for (const [key, value] of Object.entries(flat)) {
17
+ if (value === undefined || value === null) continue;
18
+
19
+ switch (key) {
20
+ case "paddingVertical":
21
+ css.paddingTop = value;
22
+ css.paddingBottom = value;
23
+ break;
24
+ case "paddingHorizontal":
25
+ css.paddingLeft = value;
26
+ css.paddingRight = value;
27
+ break;
28
+ case "marginVertical":
29
+ css.marginTop = value;
30
+ css.marginBottom = value;
31
+ break;
32
+ case "marginHorizontal":
33
+ css.marginLeft = value;
34
+ css.marginRight = value;
35
+ break;
36
+ default:
37
+ css[key] = value;
38
+ }
39
+ }
40
+
41
+ if (css.alignItems || css.justifyContent || css.flexDirection) {
42
+ css.display = css.display ?? "flex";
43
+ }
44
+
45
+ return css as CSSProperties;
46
+ }