@jlunamena/design-system 1.0.0 → 1.0.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/dist/index.d.mts CHANGED
@@ -122,6 +122,7 @@ type BodyDiagramProps = {
122
122
  overlayStyle?: BodyDiagramOverlayStyle;
123
123
  intensityByMuscle?: Record<string, BodyDiagramIntensity>;
124
124
  };
125
+
125
126
  declare const BodyDiagram: ({ view, svgMarkupByView, baseImageByView, selectedMuscles, onSelectedChange, debugForceVisible, interactionMode, palette, overlayStyle, intensityByMuscle, }: BodyDiagramProps) => react_jsx_runtime.JSX.Element;
126
127
 
127
128
  export { BodyDiagram, type BodyDiagramIntensity, type BodyDiagramOverlayStyle, type BodyDiagramPalette, type BodyDiagramProps, type BodyDiagramView, type Colors, type Radius, type Shadows, type Spacing, type Typography, colors, radius, shadows, spacing, typography };
package/dist/index.d.ts CHANGED
@@ -122,6 +122,7 @@ type BodyDiagramProps = {
122
122
  overlayStyle?: BodyDiagramOverlayStyle;
123
123
  intensityByMuscle?: Record<string, BodyDiagramIntensity>;
124
124
  };
125
+
125
126
  declare const BodyDiagram: ({ view, svgMarkupByView, baseImageByView, selectedMuscles, onSelectedChange, debugForceVisible, interactionMode, palette, overlayStyle, intensityByMuscle, }: BodyDiagramProps) => react_jsx_runtime.JSX.Element;
126
127
 
127
128
  export { BodyDiagram, type BodyDiagramIntensity, type BodyDiagramOverlayStyle, type BodyDiagramPalette, type BodyDiagramProps, type BodyDiagramView, type Colors, type Radius, type Shadows, type Spacing, type Typography, colors, radius, shadows, spacing, typography };
package/dist/index.js CHANGED
@@ -166,6 +166,17 @@ var resolveBodyDiagramMuscleState = (input) => {
166
166
  isDebugForced
167
167
  };
168
168
  };
169
+
170
+ // src/components/body-diagram/toggleMuscle.ts
171
+ var toggleMuscle = (selectedMuscles, key) => {
172
+ const next = new Set(selectedMuscles);
173
+ if (next.has(key)) {
174
+ next.delete(key);
175
+ } else {
176
+ next.add(key);
177
+ }
178
+ return Array.from(next);
179
+ };
169
180
  var BodyDiagram = ({
170
181
  view,
171
182
  svgMarkupByView,
@@ -188,13 +199,7 @@ var BodyDiagram = ({
188
199
  const element = target.closest("[data-muscle-key]");
189
200
  const key = element?.getAttribute("data-muscle-key");
190
201
  if (!key) return;
191
- const next = new Set(selectedMuscles);
192
- if (next.has(key)) {
193
- next.delete(key);
194
- } else {
195
- next.add(key);
196
- }
197
- onSelectedChange(Array.from(next));
202
+ onSelectedChange(toggleMuscle(selectedMuscles, key));
198
203
  },
199
204
  [interactionMode, onSelectedChange, selectedMuscles]
200
205
  );
package/dist/index.mjs CHANGED
@@ -164,6 +164,17 @@ var resolveBodyDiagramMuscleState = (input) => {
164
164
  isDebugForced
165
165
  };
166
166
  };
167
+
168
+ // src/components/body-diagram/toggleMuscle.ts
169
+ var toggleMuscle = (selectedMuscles, key) => {
170
+ const next = new Set(selectedMuscles);
171
+ if (next.has(key)) {
172
+ next.delete(key);
173
+ } else {
174
+ next.add(key);
175
+ }
176
+ return Array.from(next);
177
+ };
167
178
  var BodyDiagram = ({
168
179
  view,
169
180
  svgMarkupByView,
@@ -186,13 +197,7 @@ var BodyDiagram = ({
186
197
  const element = target.closest("[data-muscle-key]");
187
198
  const key = element?.getAttribute("data-muscle-key");
188
199
  if (!key) return;
189
- const next = new Set(selectedMuscles);
190
- if (next.has(key)) {
191
- next.delete(key);
192
- } else {
193
- next.add(key);
194
- }
195
- onSelectedChange(Array.from(next));
200
+ onSelectedChange(toggleMuscle(selectedMuscles, key));
196
201
  },
197
202
  [interactionMode, onSelectedChange, selectedMuscles]
198
203
  );
@@ -0,0 +1,231 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var reactNative = require('react-native');
5
+ var reactNativeSvg = require('react-native-svg');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ // src/tokens/colors.ts
9
+ var colors = {
10
+ primary: "#FDC026",
11
+ accent: "#6AABDE",
12
+ bodyDiagram: {
13
+ muscleFill: "#FFBF00",
14
+ muscleStroke: "#FF0090",
15
+ muscleStrokeWidth: 2,
16
+ muscleOpacity: 1
17
+ },
18
+ background: {
19
+ default: "#161C26",
20
+ muted: "#1C2434",
21
+ highlight: "#383040",
22
+ depth: "#08080A"
23
+ },
24
+ text: {
25
+ primary: "#E8E8E8",
26
+ secondary: "#9B9B9B"
27
+ }
28
+ };
29
+
30
+ // src/tokens/spacing.ts
31
+ var spacing = {
32
+ big: 32,
33
+ default: 24,
34
+ small: 12,
35
+ textHorizontal: 4,
36
+ textVertical: 0
37
+ };
38
+
39
+ // src/tokens/radius.ts
40
+ var radius = {
41
+ button: 4,
42
+ card: 8,
43
+ input: 4,
44
+ full: 9999
45
+ };
46
+
47
+ // src/tokens/typography.ts
48
+ var typography = {
49
+ size: {
50
+ xs: 11,
51
+ sm: 13,
52
+ base: 15,
53
+ md: 17,
54
+ lg: 20,
55
+ xl: 24,
56
+ "2xl": 30,
57
+ "3xl": 36
58
+ },
59
+ weight: {
60
+ regular: "400",
61
+ medium: "500",
62
+ semibold: "600",
63
+ bold: "700"
64
+ },
65
+ lineHeight: {
66
+ tight: 1.2,
67
+ normal: 1.5,
68
+ relaxed: 1.75
69
+ }
70
+ };
71
+
72
+ // src/tokens/shadows.ts
73
+ var shadows = {
74
+ sm: {
75
+ shadowColor: colors.background.depth,
76
+ shadowOffset: { width: 0, height: 1 },
77
+ shadowOpacity: 0.4,
78
+ shadowRadius: 2,
79
+ elevation: 2
80
+ },
81
+ md: {
82
+ shadowColor: colors.background.depth,
83
+ shadowOffset: { width: 0, height: 4 },
84
+ shadowOpacity: 0.5,
85
+ shadowRadius: 8,
86
+ elevation: 4
87
+ },
88
+ lg: {
89
+ shadowColor: colors.background.depth,
90
+ shadowOffset: { width: 0, height: 8 },
91
+ shadowOpacity: 0.6,
92
+ shadowRadius: 16,
93
+ elevation: 8
94
+ }
95
+ };
96
+
97
+ // src/utils/bodyDiagramState.ts
98
+ var DEFAULT_LEVEL_OPACITY = {
99
+ off: 0,
100
+ low: 0.2,
101
+ medium: 0.5,
102
+ high: 0.9
103
+ };
104
+ var DEFAULT_DEBUG_STYLE = {
105
+ fill: "red",
106
+ stroke: "yellow",
107
+ strokeWidth: 4,
108
+ opacity: 1
109
+ };
110
+ var DEFAULT_PALETTE = {
111
+ muscleFill: colors.bodyDiagram.muscleFill,
112
+ muscleStroke: colors.bodyDiagram.muscleStroke,
113
+ muscleStrokeWidth: colors.bodyDiagram.muscleStrokeWidth,
114
+ muscleOpacity: colors.bodyDiagram.muscleOpacity
115
+ };
116
+ var LEVELS = ["off", "low", "medium", "high"];
117
+ var resolveBodyDiagramTheme = (input = {}) => {
118
+ const palette = { ...DEFAULT_PALETTE, ...input.palette };
119
+ const opacityByLevel = { ...DEFAULT_LEVEL_OPACITY, ...input.levelOpacity };
120
+ const baseOpacity = palette.muscleOpacity ?? 1;
121
+ const levels = LEVELS.reduce(
122
+ (acc, level) => {
123
+ acc[level] = {
124
+ fill: palette.muscleFill ?? "",
125
+ stroke: palette.muscleStroke,
126
+ strokeWidth: palette.muscleStrokeWidth,
127
+ opacity: baseOpacity * (opacityByLevel[level] ?? 1)
128
+ };
129
+ return acc;
130
+ },
131
+ {
132
+ off: { fill: "", opacity: 0 },
133
+ low: { fill: "", opacity: 0 },
134
+ medium: { fill: "", opacity: 0 },
135
+ high: { fill: "", opacity: 0 }
136
+ }
137
+ );
138
+ return {
139
+ levels,
140
+ debug: input.debugStyle ?? DEFAULT_DEBUG_STYLE
141
+ };
142
+ };
143
+ var resolveBodyDiagramMuscleState = (input) => {
144
+ const { muscleKey, selectedMuscles, intensityByMuscle, debugForceVisible } = input;
145
+ const explicitLevel = intensityByMuscle?.[muscleKey];
146
+ let level = "off";
147
+ let source = "defaultOff";
148
+ if (explicitLevel) {
149
+ level = explicitLevel;
150
+ source = "explicit";
151
+ } else if (selectedMuscles.includes(muscleKey)) {
152
+ level = "high";
153
+ source = "selectedFallback";
154
+ }
155
+ const theme = input.theme ?? resolveBodyDiagramTheme({ palette: input.palette });
156
+ const isDebugForced = Boolean(debugForceVisible);
157
+ const style = isDebugForced ? theme.debug ?? DEFAULT_DEBUG_STYLE : theme.levels[level];
158
+ const shouldRender = isDebugForced ? true : level !== "off";
159
+ const interactionMode = input.interactionMode ?? "auto";
160
+ const interactive = interactionMode === "readonly" ? false : interactionMode === "editable" ? true : level !== "off";
161
+ return {
162
+ key: muscleKey,
163
+ level,
164
+ interactive,
165
+ style,
166
+ source,
167
+ shouldRender,
168
+ isDebugForced
169
+ };
170
+ };
171
+ var styleMarkup = (markup, params) => {
172
+ const { selectedMuscles, intensityByMuscle, palette, debugForceVisible, interactionMode } = params;
173
+ const theme = resolveBodyDiagramTheme({ palette });
174
+ return markup.replace(/<(\w+)([^>]*?\bdata-muscle-key="([^"]+)"[^>]*?)>/g, (match, tag, attrs, key) => {
175
+ const resolved = resolveBodyDiagramMuscleState({
176
+ muscleKey: key,
177
+ selectedMuscles,
178
+ intensityByMuscle,
179
+ palette,
180
+ debugForceVisible,
181
+ theme,
182
+ interactionMode
183
+ });
184
+ const isOff = resolved.level === "off";
185
+ const fill = isOff && !resolved.isDebugForced ? "rgba(0,0,0,0)" : resolved.style.fill || void 0;
186
+ const parts = [];
187
+ if (fill) parts.push(`fill="${fill}"`);
188
+ if (resolved.style.stroke) parts.push(`stroke="${resolved.style.stroke}"`);
189
+ if (resolved.style.strokeWidth != null) parts.push(`stroke-width="${resolved.style.strokeWidth}"`);
190
+ parts.push(`opacity="${resolved.style.opacity}"`);
191
+ return `<${tag}${attrs} ${parts.join(" ")}>`;
192
+ });
193
+ };
194
+ var BodyDiagram = ({
195
+ view,
196
+ svgMarkupByView,
197
+ selectedMuscles,
198
+ onSelectedChange,
199
+ debugForceVisible = false,
200
+ interactionMode = "auto",
201
+ palette,
202
+ intensityByMuscle
203
+ }) => {
204
+ const svgMarkup = svgMarkupByView[view] || "";
205
+ const xml = react.useMemo(
206
+ () => styleMarkup(svgMarkup, {
207
+ selectedMuscles,
208
+ intensityByMuscle,
209
+ palette,
210
+ debugForceVisible,
211
+ interactionMode
212
+ }),
213
+ [svgMarkup, selectedMuscles, intensityByMuscle, palette, debugForceVisible, interactionMode]
214
+ );
215
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.container, children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSvg.SvgXml, { xml, width: "100%", height: "100%", preserveAspectRatio: "xMidYMid meet" }) });
216
+ };
217
+ var styles = reactNative.StyleSheet.create({
218
+ container: {
219
+ flex: 1,
220
+ width: "100%",
221
+ height: "100%",
222
+ overflow: "hidden"
223
+ }
224
+ });
225
+
226
+ exports.BodyDiagram = BodyDiagram;
227
+ exports.colors = colors;
228
+ exports.radius = radius;
229
+ exports.shadows = shadows;
230
+ exports.spacing = spacing;
231
+ exports.typography = typography;
@@ -0,0 +1,224 @@
1
+ import { useMemo } from 'react';
2
+ import { StyleSheet, View } from 'react-native';
3
+ import { SvgXml } from 'react-native-svg';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ // src/tokens/colors.ts
7
+ var colors = {
8
+ primary: "#FDC026",
9
+ accent: "#6AABDE",
10
+ bodyDiagram: {
11
+ muscleFill: "#FFBF00",
12
+ muscleStroke: "#FF0090",
13
+ muscleStrokeWidth: 2,
14
+ muscleOpacity: 1
15
+ },
16
+ background: {
17
+ default: "#161C26",
18
+ muted: "#1C2434",
19
+ highlight: "#383040",
20
+ depth: "#08080A"
21
+ },
22
+ text: {
23
+ primary: "#E8E8E8",
24
+ secondary: "#9B9B9B"
25
+ }
26
+ };
27
+
28
+ // src/tokens/spacing.ts
29
+ var spacing = {
30
+ big: 32,
31
+ default: 24,
32
+ small: 12,
33
+ textHorizontal: 4,
34
+ textVertical: 0
35
+ };
36
+
37
+ // src/tokens/radius.ts
38
+ var radius = {
39
+ button: 4,
40
+ card: 8,
41
+ input: 4,
42
+ full: 9999
43
+ };
44
+
45
+ // src/tokens/typography.ts
46
+ var typography = {
47
+ size: {
48
+ xs: 11,
49
+ sm: 13,
50
+ base: 15,
51
+ md: 17,
52
+ lg: 20,
53
+ xl: 24,
54
+ "2xl": 30,
55
+ "3xl": 36
56
+ },
57
+ weight: {
58
+ regular: "400",
59
+ medium: "500",
60
+ semibold: "600",
61
+ bold: "700"
62
+ },
63
+ lineHeight: {
64
+ tight: 1.2,
65
+ normal: 1.5,
66
+ relaxed: 1.75
67
+ }
68
+ };
69
+
70
+ // src/tokens/shadows.ts
71
+ var shadows = {
72
+ sm: {
73
+ shadowColor: colors.background.depth,
74
+ shadowOffset: { width: 0, height: 1 },
75
+ shadowOpacity: 0.4,
76
+ shadowRadius: 2,
77
+ elevation: 2
78
+ },
79
+ md: {
80
+ shadowColor: colors.background.depth,
81
+ shadowOffset: { width: 0, height: 4 },
82
+ shadowOpacity: 0.5,
83
+ shadowRadius: 8,
84
+ elevation: 4
85
+ },
86
+ lg: {
87
+ shadowColor: colors.background.depth,
88
+ shadowOffset: { width: 0, height: 8 },
89
+ shadowOpacity: 0.6,
90
+ shadowRadius: 16,
91
+ elevation: 8
92
+ }
93
+ };
94
+
95
+ // src/utils/bodyDiagramState.ts
96
+ var DEFAULT_LEVEL_OPACITY = {
97
+ off: 0,
98
+ low: 0.2,
99
+ medium: 0.5,
100
+ high: 0.9
101
+ };
102
+ var DEFAULT_DEBUG_STYLE = {
103
+ fill: "red",
104
+ stroke: "yellow",
105
+ strokeWidth: 4,
106
+ opacity: 1
107
+ };
108
+ var DEFAULT_PALETTE = {
109
+ muscleFill: colors.bodyDiagram.muscleFill,
110
+ muscleStroke: colors.bodyDiagram.muscleStroke,
111
+ muscleStrokeWidth: colors.bodyDiagram.muscleStrokeWidth,
112
+ muscleOpacity: colors.bodyDiagram.muscleOpacity
113
+ };
114
+ var LEVELS = ["off", "low", "medium", "high"];
115
+ var resolveBodyDiagramTheme = (input = {}) => {
116
+ const palette = { ...DEFAULT_PALETTE, ...input.palette };
117
+ const opacityByLevel = { ...DEFAULT_LEVEL_OPACITY, ...input.levelOpacity };
118
+ const baseOpacity = palette.muscleOpacity ?? 1;
119
+ const levels = LEVELS.reduce(
120
+ (acc, level) => {
121
+ acc[level] = {
122
+ fill: palette.muscleFill ?? "",
123
+ stroke: palette.muscleStroke,
124
+ strokeWidth: palette.muscleStrokeWidth,
125
+ opacity: baseOpacity * (opacityByLevel[level] ?? 1)
126
+ };
127
+ return acc;
128
+ },
129
+ {
130
+ off: { fill: "", opacity: 0 },
131
+ low: { fill: "", opacity: 0 },
132
+ medium: { fill: "", opacity: 0 },
133
+ high: { fill: "", opacity: 0 }
134
+ }
135
+ );
136
+ return {
137
+ levels,
138
+ debug: input.debugStyle ?? DEFAULT_DEBUG_STYLE
139
+ };
140
+ };
141
+ var resolveBodyDiagramMuscleState = (input) => {
142
+ const { muscleKey, selectedMuscles, intensityByMuscle, debugForceVisible } = input;
143
+ const explicitLevel = intensityByMuscle?.[muscleKey];
144
+ let level = "off";
145
+ let source = "defaultOff";
146
+ if (explicitLevel) {
147
+ level = explicitLevel;
148
+ source = "explicit";
149
+ } else if (selectedMuscles.includes(muscleKey)) {
150
+ level = "high";
151
+ source = "selectedFallback";
152
+ }
153
+ const theme = input.theme ?? resolveBodyDiagramTheme({ palette: input.palette });
154
+ const isDebugForced = Boolean(debugForceVisible);
155
+ const style = isDebugForced ? theme.debug ?? DEFAULT_DEBUG_STYLE : theme.levels[level];
156
+ const shouldRender = isDebugForced ? true : level !== "off";
157
+ const interactionMode = input.interactionMode ?? "auto";
158
+ const interactive = interactionMode === "readonly" ? false : interactionMode === "editable" ? true : level !== "off";
159
+ return {
160
+ key: muscleKey,
161
+ level,
162
+ interactive,
163
+ style,
164
+ source,
165
+ shouldRender,
166
+ isDebugForced
167
+ };
168
+ };
169
+ var styleMarkup = (markup, params) => {
170
+ const { selectedMuscles, intensityByMuscle, palette, debugForceVisible, interactionMode } = params;
171
+ const theme = resolveBodyDiagramTheme({ palette });
172
+ return markup.replace(/<(\w+)([^>]*?\bdata-muscle-key="([^"]+)"[^>]*?)>/g, (match, tag, attrs, key) => {
173
+ const resolved = resolveBodyDiagramMuscleState({
174
+ muscleKey: key,
175
+ selectedMuscles,
176
+ intensityByMuscle,
177
+ palette,
178
+ debugForceVisible,
179
+ theme,
180
+ interactionMode
181
+ });
182
+ const isOff = resolved.level === "off";
183
+ const fill = isOff && !resolved.isDebugForced ? "rgba(0,0,0,0)" : resolved.style.fill || void 0;
184
+ const parts = [];
185
+ if (fill) parts.push(`fill="${fill}"`);
186
+ if (resolved.style.stroke) parts.push(`stroke="${resolved.style.stroke}"`);
187
+ if (resolved.style.strokeWidth != null) parts.push(`stroke-width="${resolved.style.strokeWidth}"`);
188
+ parts.push(`opacity="${resolved.style.opacity}"`);
189
+ return `<${tag}${attrs} ${parts.join(" ")}>`;
190
+ });
191
+ };
192
+ var BodyDiagram = ({
193
+ view,
194
+ svgMarkupByView,
195
+ selectedMuscles,
196
+ onSelectedChange,
197
+ debugForceVisible = false,
198
+ interactionMode = "auto",
199
+ palette,
200
+ intensityByMuscle
201
+ }) => {
202
+ const svgMarkup = svgMarkupByView[view] || "";
203
+ const xml = useMemo(
204
+ () => styleMarkup(svgMarkup, {
205
+ selectedMuscles,
206
+ intensityByMuscle,
207
+ palette,
208
+ debugForceVisible,
209
+ interactionMode
210
+ }),
211
+ [svgMarkup, selectedMuscles, intensityByMuscle, palette, debugForceVisible, interactionMode]
212
+ );
213
+ return /* @__PURE__ */ jsx(View, { style: styles.container, children: /* @__PURE__ */ jsx(SvgXml, { xml, width: "100%", height: "100%", preserveAspectRatio: "xMidYMid meet" }) });
214
+ };
215
+ var styles = StyleSheet.create({
216
+ container: {
217
+ flex: 1,
218
+ width: "100%",
219
+ height: "100%",
220
+ overflow: "hidden"
221
+ }
222
+ });
223
+
224
+ export { BodyDiagram, colors, radius, shadows, spacing, typography };
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@jlunamena/design-system",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "PT Design System",
5
5
  "main": "dist/index.js",
6
+ "react-native": "dist/index.native.js",
6
7
  "module": "dist/index.mjs",
7
8
  "types": "dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
11
+ "react-native": "./dist/index.native.js",
10
12
  "types": "./dist/index.d.ts",
11
13
  "import": "./dist/index.mjs",
12
14
  "require": "./dist/index.js"
@@ -23,7 +25,17 @@
23
25
  "generate:exports": "node scripts/generate-exports.mjs"
24
26
  },
25
27
  "peerDependencies": {
26
- "react": ">=18.0.0"
28
+ "react": ">=18.0.0",
29
+ "react-native": "*",
30
+ "react-native-svg": "*"
31
+ },
32
+ "peerDependenciesMeta": {
33
+ "react-native": {
34
+ "optional": true
35
+ },
36
+ "react-native-svg": {
37
+ "optional": true
38
+ }
27
39
  },
28
40
  "devDependencies": {
29
41
  "@storybook/addon-essentials": "^8.6.0",