@themodcraft/core-ui 1.1.0 → 1.1.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.
Files changed (52) hide show
  1. package/dist/components/button/Button.d.ts +1 -1
  2. package/dist/components/button/Button.js +72 -114
  3. package/dist/components/button/Button.module.css +1 -0
  4. package/dist/components/button/index.js +1 -1
  5. package/dist/components/checkbox/Checkbox.js +27 -45
  6. package/dist/components/checkbox/Checkbox.module.css +1 -0
  7. package/dist/components/checkbox/Switch.js +32 -77
  8. package/dist/components/checkbox/Switch.module.css +1 -0
  9. package/dist/components/checkbox/index.js +2 -2
  10. package/dist/components/code-block/CodeBlock.js +119 -53
  11. package/dist/components/code-block/CodeBlock.module.css +1 -0
  12. package/dist/components/code-block/index.js +1 -1
  13. package/dist/components/divider/Divider.d.ts +1 -1
  14. package/dist/components/divider/Divider.js +20 -34
  15. package/dist/components/divider/Divider.module.css +1 -0
  16. package/dist/components/divider/index.js +1 -1
  17. package/dist/components/radio/Radio.client.d.ts +2 -0
  18. package/dist/components/radio/Radio.client.js +142 -0
  19. package/dist/components/radio/Radio.d.ts +1 -1
  20. package/dist/components/radio/Radio.js +61 -76
  21. package/dist/components/radio/Radio.module.css +1 -0
  22. package/dist/components/radio/index.d.ts +1 -0
  23. package/dist/components/radio/index.js +2 -1
  24. package/dist/components/slider/Slider.js +31 -84
  25. package/dist/components/slider/Slider.module.css +1 -0
  26. package/dist/components/slider/index.js +1 -1
  27. package/dist/components/text-input/AuthFields.js +57 -11
  28. package/dist/components/text-input/TextArea.js +32 -17
  29. package/dist/components/text-input/TextInput.js +32 -13
  30. package/dist/components/text-input/TextInput.module.css +1 -0
  31. package/dist/components/text-input/contrast.client.d.ts +9 -0
  32. package/dist/components/text-input/contrast.client.js +132 -0
  33. package/dist/components/text-input/index.d.ts +1 -0
  34. package/dist/components/text-input/index.js +4 -3
  35. package/dist/components/text-input/shared.d.ts +1 -26
  36. package/dist/components/text-input/shared.js +4 -112
  37. package/dist/config/component-config.js +6 -4
  38. package/dist/index.js +16 -11
  39. package/dist/path-map/asset-path-map.js +28 -21
  40. package/dist/path-map/index.js +1 -1
  41. package/dist/styles/index.css +1 -67
  42. package/dist/tokens/default-theme.json.js +34 -0
  43. package/dist/tokens/index.js +1 -2
  44. package/dist/utils/color.js +49 -60
  45. package/package.json +7 -7
  46. package/dist/components/button/Button.types.js +0 -1
  47. package/dist/components/checkbox/Checkbox.types.js +0 -1
  48. package/dist/components/code-block/CodeBlock.types.js +0 -1
  49. package/dist/components/divider/Divider.types.js +0 -1
  50. package/dist/components/radio/Radio.types.js +0 -1
  51. package/dist/components/slider/Slider.types.js +0 -1
  52. package/dist/components/text-input/TextInput.types.js +0 -1
@@ -0,0 +1,132 @@
1
+ "use client";
2
+ import { c } from 'react/compiler-runtime';
3
+ import { useRef, useState, useEffect } from 'react';
4
+ import { rgbToHex, getReadableTextColor } from '../../utils/color.js';
5
+
6
+ function isTransparentBackground(color) {
7
+ return !color || color === "transparent" || /rgba\([^)]*,\s*(?:0|0?\.0+)\s*\)$/i.test(color);
8
+ }
9
+ function getEffectiveBackground(element) {
10
+ let current = element;
11
+ while (current) {
12
+ const background = window.getComputedStyle(current).backgroundColor;
13
+ if (!isTransparentBackground(background)) {
14
+ return background;
15
+ }
16
+ current = current.parentElement;
17
+ }
18
+ const bodyBackground = window.getComputedStyle(document.body).backgroundColor;
19
+ return isTransparentBackground(bodyBackground) ? window.getComputedStyle(document.documentElement).backgroundColor : bodyBackground;
20
+ }
21
+ function useContrastedFieldStyle(style) {
22
+ const $ = c(8);
23
+ const ref = useRef(null);
24
+ const [textColor, setTextColor] = useState();
25
+ let t0;
26
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
27
+ t0 = () => {
28
+ const element = ref.current;
29
+ if (!element) {
30
+ return;
31
+ }
32
+ const hex = rgbToHex(getEffectiveBackground(element));
33
+ if (hex) {
34
+ setTextColor(getReadableTextColor(hex));
35
+ }
36
+ };
37
+ $[0] = t0;
38
+ } else {
39
+ t0 = $[0];
40
+ }
41
+ let t1;
42
+ if ($[1] !== style) {
43
+ t1 = [style];
44
+ $[1] = style;
45
+ $[2] = t1;
46
+ } else {
47
+ t1 = $[2];
48
+ }
49
+ useEffect(t0, t1);
50
+ let t2;
51
+ if ($[3] !== style || $[4] !== textColor) {
52
+ t2 = {
53
+ "--tmc-field-auto-text": textColor,
54
+ ...style
55
+ };
56
+ $[3] = style;
57
+ $[4] = textColor;
58
+ $[5] = t2;
59
+ } else {
60
+ t2 = $[5];
61
+ }
62
+ const t3 = t2;
63
+ let t4;
64
+ if ($[6] !== t3) {
65
+ t4 = {
66
+ ref,
67
+ style: t3
68
+ };
69
+ $[6] = t3;
70
+ $[7] = t4;
71
+ } else {
72
+ t4 = $[7];
73
+ }
74
+ return t4;
75
+ }
76
+ function useContrastedInputStyle(style) {
77
+ const $ = c(8);
78
+ const ref = useRef(null);
79
+ const [textColor, setTextColor] = useState();
80
+ let t0;
81
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
82
+ t0 = () => {
83
+ const element = ref.current;
84
+ if (!element) {
85
+ return;
86
+ }
87
+ const hex = rgbToHex(getEffectiveBackground(element));
88
+ if (hex) {
89
+ setTextColor(getReadableTextColor(hex));
90
+ }
91
+ };
92
+ $[0] = t0;
93
+ } else {
94
+ t0 = $[0];
95
+ }
96
+ let t1;
97
+ if ($[1] !== style) {
98
+ t1 = [style];
99
+ $[1] = style;
100
+ $[2] = t1;
101
+ } else {
102
+ t1 = $[2];
103
+ }
104
+ useEffect(t0, t1);
105
+ let t2;
106
+ if ($[3] !== style || $[4] !== textColor) {
107
+ t2 = {
108
+ "--tmc-input-auto-text": textColor,
109
+ ...style
110
+ };
111
+ $[3] = style;
112
+ $[4] = textColor;
113
+ $[5] = t2;
114
+ } else {
115
+ t2 = $[5];
116
+ }
117
+ const t3 = t2;
118
+ let t4;
119
+ if ($[6] !== t3) {
120
+ t4 = {
121
+ ref,
122
+ style: t3
123
+ };
124
+ $[6] = t3;
125
+ $[7] = t4;
126
+ } else {
127
+ t4 = $[7];
128
+ }
129
+ return t4;
130
+ }
131
+
132
+ export { useContrastedFieldStyle, useContrastedInputStyle };
@@ -1,5 +1,6 @@
1
1
  export { EmailField, PasswordField, PhoneNumberField, UsernameField } from "./AuthFields";
2
2
  export { TextArea } from "./TextArea";
3
3
  export { TextInput } from "./TextInput";
4
+ export { useContrastedFieldStyle, useContrastedInputStyle } from "./contrast.client";
4
5
  export type { AuthFieldProps } from "./AuthFields";
5
6
  export type { TextAreaProps, TextInputProps } from "./TextInput.types";
@@ -1,3 +1,4 @@
1
- export { EmailField, PasswordField, PhoneNumberField, UsernameField } from "./AuthFields";
2
- export { TextArea } from "./TextArea";
3
- export { TextInput } from "./TextInput";
1
+ export { EmailField, PasswordField, PhoneNumberField, UsernameField } from './AuthFields.js';
2
+ export { TextArea } from './TextArea.js';
3
+ export { TextInput } from './TextInput.js';
4
+ export { useContrastedFieldStyle, useContrastedInputStyle } from './contrast.client.js';
@@ -1,26 +1 @@
1
- import type { CSSProperties } from "react";
2
- export declare const FieldRoot: import("@emotion/styled").StyledComponent<{
3
- theme?: import("@emotion/react").Theme;
4
- as?: React.ElementType;
5
- }, import("react").DetailedHTMLProps<import("react").LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, {}>;
6
- export declare const FieldLabel: import("@emotion/styled").StyledComponent<{
7
- theme?: import("@emotion/react").Theme;
8
- as?: React.ElementType;
9
- }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {}>;
10
- export declare const FieldDescription: import("@emotion/styled").StyledComponent<{
11
- theme?: import("@emotion/react").Theme;
12
- as?: React.ElementType;
13
- }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {}>;
14
- export declare const FieldError: import("@emotion/styled").StyledComponent<{
15
- theme?: import("@emotion/react").Theme;
16
- as?: React.ElementType;
17
- }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {}>;
18
- export declare const inputSurfaceStyles = "\n background: var(--tmc-color-surface-raised, #fbfcfe);\n border: 1px solid var(--tmc-color-border, #d7dde5);\n border-radius: var(--tmc-radius-md, 6px);\n color: var(--tmc-input-text, var(--tmc-input-auto-text, var(--tmc-color-on-surface-raised, #151821)));\n font: inherit;\n outline: none;\n transition:\n background-color 0.18s ease,\n border-color 0.18s ease,\n box-shadow 0.18s ease;\n width: 100%;\n\n &::placeholder {\n color: var(--tmc-input-placeholder-text, var(--tmc-input-auto-text, var(--tmc-color-text-muted, #5f6b7a)));\n opacity: 0.72;\n }\n\n &:focus {\n border-color: var(--tmc-color-accent, #2454d6);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--tmc-color-accent, #2454d6) 24%, transparent);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.58;\n }\n\n &[aria-invalid=\"true\"] {\n border-color: var(--tmc-color-danger, #b42318);\n }\n";
19
- export declare function useContrastedFieldStyle<T extends HTMLElement>(style?: CSSProperties): {
20
- ref: import("react").RefObject<T | null>;
21
- style: CSSProperties;
22
- };
23
- export declare function useContrastedInputStyle<T extends HTMLElement>(style?: CSSProperties): {
24
- ref: import("react").RefObject<T | null>;
25
- style: CSSProperties;
26
- };
1
+ export declare function classNames(...classes: Array<string | undefined>): string;
@@ -1,113 +1,5 @@
1
- import styled from "@emotion/styled";
2
- import { useEffect, useRef, useState } from "react";
3
- import { getReadableTextColor, rgbToHex } from "../../utils/color";
4
- export const FieldRoot = styled.label `
5
- color: var(--tmc-field-label-text, var(--tmc-field-auto-text, var(--tmc-color-text, #151821)));
6
- display: grid;
7
- gap: 0.45rem;
8
- width: 100%;
9
- `;
10
- export const FieldLabel = styled.span `
11
- color: inherit;
12
- font-size: 0.9rem;
13
- font-weight: 650;
14
- `;
15
- export const FieldDescription = styled.span `
16
- color: var(--tmc-field-description-text, var(--tmc-color-text-muted, var(--tmc-field-auto-text, #5f6b7a)));
17
- font-size: 0.82rem;
18
- line-height: 1.45;
19
- `;
20
- export const FieldError = styled.span `
21
- color: var(--tmc-color-danger, #b42318);
22
- font-size: 0.82rem;
23
- line-height: 1.45;
24
- `;
25
- export const inputSurfaceStyles = `
26
- background: var(--tmc-color-surface-raised, #fbfcfe);
27
- border: 1px solid var(--tmc-color-border, #d7dde5);
28
- border-radius: var(--tmc-radius-md, 6px);
29
- color: var(--tmc-input-text, var(--tmc-input-auto-text, var(--tmc-color-on-surface-raised, #151821)));
30
- font: inherit;
31
- outline: none;
32
- transition:
33
- background-color 0.18s ease,
34
- border-color 0.18s ease,
35
- box-shadow 0.18s ease;
36
- width: 100%;
37
-
38
- &::placeholder {
39
- color: var(--tmc-input-placeholder-text, var(--tmc-input-auto-text, var(--tmc-color-text-muted, #5f6b7a)));
40
- opacity: 0.72;
41
- }
42
-
43
- &:focus {
44
- border-color: var(--tmc-color-accent, #2454d6);
45
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--tmc-color-accent, #2454d6) 24%, transparent);
46
- }
47
-
48
- &:disabled {
49
- cursor: not-allowed;
50
- opacity: 0.58;
51
- }
52
-
53
- &[aria-invalid="true"] {
54
- border-color: var(--tmc-color-danger, #b42318);
55
- }
56
- `;
57
- function isTransparentBackground(color) {
58
- return !color || color === "transparent" || /rgba\([^)]*,\s*(?:0|0?\.0+)\s*\)$/i.test(color);
59
- }
60
- function getEffectiveBackground(element) {
61
- let current = element;
62
- while (current) {
63
- const background = window.getComputedStyle(current).backgroundColor;
64
- if (!isTransparentBackground(background)) {
65
- return background;
66
- }
67
- current = current.parentElement;
68
- }
69
- const bodyBackground = window.getComputedStyle(document.body).backgroundColor;
70
- return isTransparentBackground(bodyBackground) ? window.getComputedStyle(document.documentElement).backgroundColor : bodyBackground;
71
- }
72
- export function useContrastedFieldStyle(style) {
73
- const ref = useRef(null);
74
- const [textColor, setTextColor] = useState();
75
- useEffect(() => {
76
- const element = ref.current;
77
- if (!element) {
78
- return;
79
- }
80
- const hex = rgbToHex(getEffectiveBackground(element));
81
- if (hex) {
82
- setTextColor(getReadableTextColor(hex));
83
- }
84
- }, [style]);
85
- return {
86
- ref,
87
- style: {
88
- "--tmc-field-auto-text": textColor,
89
- ...style,
90
- },
91
- };
92
- }
93
- export function useContrastedInputStyle(style) {
94
- const ref = useRef(null);
95
- const [textColor, setTextColor] = useState();
96
- useEffect(() => {
97
- const element = ref.current;
98
- if (!element) {
99
- return;
100
- }
101
- const hex = rgbToHex(getEffectiveBackground(element));
102
- if (hex) {
103
- setTextColor(getReadableTextColor(hex));
104
- }
105
- }, [style]);
106
- return {
107
- ref,
108
- style: {
109
- "--tmc-input-auto-text": textColor,
110
- ...style,
111
- },
112
- };
1
+ function classNames(...classes) {
2
+ return classes.filter(Boolean).join(" ");
113
3
  }
4
+
5
+ export { classNames };
@@ -1,6 +1,8 @@
1
- export function defineComponentConfig(config) {
2
- return config;
1
+ function defineComponentConfig(config) {
2
+ return config;
3
3
  }
4
- export function readConfigProps(config) {
5
- return config.props;
4
+ function readConfigProps(config) {
5
+ return config.props;
6
6
  }
7
+
8
+ export { defineComponentConfig, readConfigProps };
package/dist/index.js CHANGED
@@ -1,11 +1,16 @@
1
- export * from "./components/button";
2
- export * from "./components/code-block";
3
- export * from "./components/checkbox";
4
- export * from "./components/divider";
5
- export * from "./components/radio";
6
- export * from "./components/slider";
7
- export * from "./components/text-input";
8
- export * from "./config/component-config";
9
- export * from "./path-map";
10
- export * from "./tokens";
11
- export * from "./utils/color";
1
+ export { defineComponentConfig, readConfigProps } from './config/component-config.js';
2
+ export { darken, getReadableTextColor, invertAndGrayscaleHex, isValidHex, normalizeHex, rgbToHex } from './utils/color.js';
3
+ export { Button } from './components/button/Button.js';
4
+ export { Checkbox } from './components/checkbox/Checkbox.js';
5
+ export { CodeBlock } from './components/code-block/CodeBlock.js';
6
+ export { Divider } from './components/divider/Divider.js';
7
+ export { EmailField, PasswordField, PhoneNumberField, UsernameField } from './components/text-input/AuthFields.js';
8
+ export { Radio, RadioGroup } from './components/radio/Radio.js';
9
+ export { Slider } from './components/slider/Slider.js';
10
+ export { SmartRadioGroup } from './components/radio/Radio.client.js';
11
+ export { Switch } from './components/checkbox/Switch.js';
12
+ export { TextArea } from './components/text-input/TextArea.js';
13
+ export { TextInput } from './components/text-input/TextInput.js';
14
+ export { defaultAssetPathAliases, resolveAssetPath } from './path-map/asset-path-map.js';
15
+ export { default as defaultTheme } from './tokens/default-theme.json.js';
16
+ export { useContrastedFieldStyle, useContrastedInputStyle } from './components/text-input/contrast.client.js';
@@ -1,28 +1,35 @@
1
- export const defaultAssetPathAliases = {
2
- "@audios/": "resources/assets/audios/",
3
- "@audio/": "resources/assets/audios/",
4
- "@images/": "resources/assets/images/",
5
- "@videos/": "resources/assets/videos/",
1
+ const defaultAssetPathAliases = {
2
+ "@audios/": "resources/assets/audios/",
3
+ "@audio/": "resources/assets/audios/",
4
+ "@images/": "resources/assets/images/",
5
+ "@videos/": "resources/assets/videos/"
6
6
  };
7
7
  function stripEdgeSlashes(value) {
8
- return value.replace(/^\/+|\/+$/g, "");
8
+ return value.replace(/^\/+|\/+$/g, "");
9
9
  }
10
10
  function mapAlias(path, aliases) {
11
- for (const [alias, replacement] of Object.entries(aliases)) {
12
- if (path.startsWith(alias)) {
13
- return path.replace(alias, replacement);
14
- }
11
+ for (const [alias, replacement] of Object.entries(aliases)) {
12
+ if (path.startsWith(alias)) {
13
+ return path.replace(alias, replacement);
15
14
  }
16
- return path;
15
+ }
16
+ return path;
17
17
  }
18
- export function resolveAssetPath(path, { aliases = defaultAssetPathAliases, cdnBase = "https://cdn.themodcraft.net", mode = "development", publicBasePath = "", } = {}) {
19
- if (!path || /^https?:\/\//.test(path)) {
20
- return path;
21
- }
22
- const internalPath = stripEdgeSlashes(mapAlias(path, aliases));
23
- if (mode === "production") {
24
- return `${stripEdgeSlashes(cdnBase)}/${internalPath}`;
25
- }
26
- const base = stripEdgeSlashes(publicBasePath);
27
- return `/${[base, internalPath].filter(Boolean).join("/")}`;
18
+ function resolveAssetPath(path, {
19
+ aliases = defaultAssetPathAliases,
20
+ cdnBase = "https://cdn.themodcraft.net",
21
+ mode = "development",
22
+ publicBasePath = ""
23
+ } = {}) {
24
+ if (!path || /^https?:\/\//.test(path)) {
25
+ return path;
26
+ }
27
+ const internalPath = stripEdgeSlashes(mapAlias(path, aliases));
28
+ if (mode === "production") {
29
+ return `${stripEdgeSlashes(cdnBase)}/${internalPath}`;
30
+ }
31
+ const base = stripEdgeSlashes(publicBasePath);
32
+ return `/${[base, internalPath].filter(Boolean).join("/")}`;
28
33
  }
34
+
35
+ export { defaultAssetPathAliases, resolveAssetPath };
@@ -1 +1 @@
1
- export { defaultAssetPathAliases, resolveAssetPath, } from "./asset-path-map";
1
+ export { defaultAssetPathAliases, resolveAssetPath } from './asset-path-map.js';
@@ -1,67 +1 @@
1
- :root {
2
- color-scheme: light dark;
3
- --tmc-color-surface: #f3f5f8;
4
- --tmc-color-surface-muted: #e7ebf0;
5
- --tmc-color-surface-raised: #fbfcfe;
6
- --tmc-color-text: #151821;
7
- --tmc-color-text-muted: #5f6b7a;
8
- --tmc-color-border: #d7dde5;
9
- --tmc-color-accent: #2454d6;
10
- --tmc-color-accent-text: #f7faff;
11
- --tmc-color-hover: color-mix(in srgb, var(--tmc-color-accent, #2454d6) 10%, transparent);
12
- --tmc-color-focus: #d99a00;
13
- --tmc-color-danger: #b42318;
14
- --tmc-radius-sm: 4px;
15
- --tmc-radius-md: 6px;
16
- --tmc-radius-lg: 8px;
17
- }
18
-
19
- @media (prefers-color-scheme: dark) {
20
- :root {
21
- --tmc-color-surface: #181b22;
22
- --tmc-color-surface-muted: #232832;
23
- --tmc-color-surface-raised: #20242d;
24
- --tmc-color-text: #f2f5f8;
25
- --tmc-color-text-muted: #aab4c0;
26
- --tmc-color-border: #333b48;
27
- --tmc-color-accent: #6ea3ff;
28
- --tmc-color-accent-text: #10151f;
29
- --tmc-color-hover: color-mix(in srgb, var(--tmc-color-accent, #6ea3ff) 14%, transparent);
30
- --tmc-color-focus: #f2b84b;
31
- --tmc-color-danger: #ff7a70;
32
- }
33
- }
34
-
35
- :root[data-tmc-theme-mode="light"] {
36
- color-scheme: light;
37
- --tmc-color-surface: #f3f5f8;
38
- --tmc-color-surface-muted: #e7ebf0;
39
- --tmc-color-surface-raised: #fbfcfe;
40
- --tmc-color-text: #151821;
41
- --tmc-color-text-muted: #5f6b7a;
42
- --tmc-color-border: #d7dde5;
43
- --tmc-color-accent: #2454d6;
44
- --tmc-color-accent-text: #f7faff;
45
- --tmc-color-hover: color-mix(in srgb, var(--tmc-color-accent, #2454d6) 10%, transparent);
46
- --tmc-color-focus: #d99a00;
47
- --tmc-color-danger: #b42318;
48
- }
49
-
50
- :root[data-tmc-theme-mode="dark"] {
51
- color-scheme: dark;
52
- --tmc-color-surface: #181b22;
53
- --tmc-color-surface-muted: #232832;
54
- --tmc-color-surface-raised: #20242d;
55
- --tmc-color-text: #f2f5f8;
56
- --tmc-color-text-muted: #aab4c0;
57
- --tmc-color-border: #333b48;
58
- --tmc-color-accent: #6ea3ff;
59
- --tmc-color-accent-text: #10151f;
60
- --tmc-color-hover: color-mix(in srgb, var(--tmc-color-accent, #6ea3ff) 14%, transparent);
61
- --tmc-color-focus: #f2b84b;
62
- --tmc-color-danger: #ff7a70;
63
- }
64
-
65
- * {
66
- box-sizing: border-box;
67
- }
1
+ :root{color-scheme:light dark;--tmc-color-surface:#f3f5f8;--tmc-color-surface-muted:#e7ebf0;--tmc-color-surface-raised:#fbfcfe;--tmc-color-text:#151821;--tmc-color-text-muted:#5f6b7a;--tmc-color-border:#d7dde5;--tmc-color-accent:#2454d6;--tmc-color-accent-text:#f7faff;--tmc-color-hover:color-mix(in srgb,var(--tmc-color-accent,#2454d6) 10%,transparent);--tmc-color-focus:#d99a00;--tmc-color-danger:#b42318;--tmc-radius-sm:4px;--tmc-radius-md:6px;--tmc-radius-lg:8px}@media (prefers-color-scheme:dark){:root{--tmc-color-surface:#181b22;--tmc-color-surface-muted:#232832;--tmc-color-surface-raised:#20242d;--tmc-color-text:#f2f5f8;--tmc-color-text-muted:#aab4c0;--tmc-color-border:#333b48;--tmc-color-accent:#6ea3ff;--tmc-color-accent-text:#10151f;--tmc-color-hover:color-mix(in srgb,var(--tmc-color-accent,#6ea3ff) 14%,transparent);--tmc-color-focus:#f2b84b;--tmc-color-danger:#ff7a70}}:root[data-tmc-theme-mode=light]{color-scheme:light;--tmc-color-surface:#f3f5f8;--tmc-color-surface-muted:#e7ebf0;--tmc-color-surface-raised:#fbfcfe;--tmc-color-text:#151821;--tmc-color-text-muted:#5f6b7a;--tmc-color-border:#d7dde5;--tmc-color-accent:#2454d6;--tmc-color-accent-text:#f7faff;--tmc-color-hover:color-mix(in srgb,var(--tmc-color-accent,#2454d6) 10%,transparent);--tmc-color-focus:#d99a00;--tmc-color-danger:#b42318}:root[data-tmc-theme-mode=dark]{color-scheme:dark;--tmc-color-surface:#181b22;--tmc-color-surface-muted:#232832;--tmc-color-surface-raised:#20242d;--tmc-color-text:#f2f5f8;--tmc-color-text-muted:#aab4c0;--tmc-color-border:#333b48;--tmc-color-accent:#6ea3ff;--tmc-color-accent-text:#10151f;--tmc-color-hover:color-mix(in srgb,var(--tmc-color-accent,#6ea3ff) 14%,transparent);--tmc-color-focus:#f2b84b;--tmc-color-danger:#ff7a70}*{box-sizing:border-box}
@@ -0,0 +1,34 @@
1
+ const name = "tmc-default";
2
+ const color = {
3
+ surface: "#ffffff",
4
+ surfaceMuted: "#f6f7f9",
5
+ surfaceRaised: "#ffffff",
6
+ text: "#111827",
7
+ textMuted: "#5f6b7a",
8
+ border: "#d7dde5",
9
+ accent: "#0b63ce",
10
+ accentText: "#ffffff",
11
+ focus: "#ffb020",
12
+ danger: "#b42318"
13
+ };
14
+ const radius = {
15
+ sm: "4px",
16
+ md: "6px",
17
+ lg: "8px"
18
+ };
19
+ const space = {
20
+ "1": "4px",
21
+ "2": "8px",
22
+ "3": "12px",
23
+ "4": "16px",
24
+ "6": "24px",
25
+ "8": "32px"
26
+ };
27
+ const defaultTheme = {
28
+ name: name,
29
+ color: color,
30
+ radius: radius,
31
+ space: space
32
+ };
33
+
34
+ export { color, defaultTheme as default, name, radius, space };
@@ -1,2 +1 @@
1
- import defaultTheme from "./default-theme.json";
2
- export { defaultTheme };
1
+ export { default as defaultTheme } from './default-theme.json.js';
@@ -1,66 +1,55 @@
1
- export function isValidHex(hex) {
2
- return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(hex.trim());
1
+ function isValidHex(hex) {
2
+ return /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(hex.trim());
3
3
  }
4
- export function normalizeHex(hex) {
5
- const value = hex.trim();
6
- if (/^#[0-9A-Fa-f]{3}$/.test(value)) {
7
- return `#${value
8
- .slice(1)
9
- .split("")
10
- .map((channel) => `${channel}${channel}`)
11
- .join("")}`.toUpperCase();
12
- }
13
- if (/^#[0-9A-Fa-f]{6}$/.test(value)) {
14
- return value.toUpperCase();
15
- }
16
- return null;
4
+ function normalizeHex(hex) {
5
+ const value = hex.trim();
6
+ if (/^#[0-9A-Fa-f]{3}$/.test(value)) {
7
+ return `#${value.slice(1).split("").map(channel => `${channel}${channel}`).join("")}`.toUpperCase();
8
+ }
9
+ if (/^#[0-9A-Fa-f]{6}$/.test(value)) {
10
+ return value.toUpperCase();
11
+ }
12
+ return null;
17
13
  }
18
- export function rgbToHex(rgb) {
19
- const result = rgb.match(/\d+/g);
20
- if (!result || result.length < 3) {
21
- return null;
22
- }
23
- const [r, g, b] = result.map(Number);
24
- return `#${[r, g, b]
25
- .map((channel) => Math.max(0, Math.min(255, channel)).toString(16).padStart(2, "0"))
26
- .join("")
27
- .toUpperCase()}`;
14
+ function rgbToHex(rgb) {
15
+ const result = rgb.match(/\d+/g);
16
+ if (!result || result.length < 3) {
17
+ return null;
18
+ }
19
+ const [r, g, b] = result.map(Number);
20
+ return `#${[r, g, b].map(channel => Math.max(0, Math.min(255, channel)).toString(16).padStart(2, "0")).join("").toUpperCase()}`;
28
21
  }
29
- export function darken(hex, amount) {
30
- const normalized = normalizeHex(hex);
31
- if (!normalized) {
32
- return "#000000";
33
- }
34
- const r = Math.max(0, parseInt(normalized.slice(1, 3), 16) - amount);
35
- const g = Math.max(0, parseInt(normalized.slice(3, 5), 16) - amount);
36
- const b = Math.max(0, parseInt(normalized.slice(5, 7), 16) - amount);
37
- return `#${[r, g, b]
38
- .map((channel) => channel.toString(16).padStart(2, "0"))
39
- .join("")
40
- .toUpperCase()}`;
22
+ function darken(hex, amount) {
23
+ const normalized = normalizeHex(hex);
24
+ if (!normalized) {
25
+ return "#000000";
26
+ }
27
+ const r = Math.max(0, parseInt(normalized.slice(1, 3), 16) - amount);
28
+ const g = Math.max(0, parseInt(normalized.slice(3, 5), 16) - amount);
29
+ const b = Math.max(0, parseInt(normalized.slice(5, 7), 16) - amount);
30
+ return `#${[r, g, b].map(channel => channel.toString(16).padStart(2, "0")).join("").toUpperCase()}`;
41
31
  }
42
- export function invertAndGrayscaleHex(hex) {
43
- const normalized = normalizeHex(hex);
44
- if (!normalized) {
45
- return "#000000";
46
- }
47
- const r = 255 - parseInt(normalized.slice(1, 3), 16);
48
- const g = 255 - parseInt(normalized.slice(3, 5), 16);
49
- const b = 255 - parseInt(normalized.slice(5, 7), 16);
50
- const gray = Math.round(0.3 * r + 0.59 * g + 0.11 * b);
51
- return `#${[gray, gray, gray]
52
- .map((channel) => channel.toString(16).padStart(2, "0"))
53
- .join("")
54
- .toUpperCase()}`;
32
+ function invertAndGrayscaleHex(hex) {
33
+ const normalized = normalizeHex(hex);
34
+ if (!normalized) {
35
+ return "#000000";
36
+ }
37
+ const r = 255 - parseInt(normalized.slice(1, 3), 16);
38
+ const g = 255 - parseInt(normalized.slice(3, 5), 16);
39
+ const b = 255 - parseInt(normalized.slice(5, 7), 16);
40
+ const gray = Math.round(0.3 * r + 0.59 * g + 0.11 * b);
41
+ return `#${[gray, gray, gray].map(channel => channel.toString(16).padStart(2, "0")).join("").toUpperCase()}`;
55
42
  }
56
- export function getReadableTextColor(hex) {
57
- const normalized = normalizeHex(hex);
58
- if (!normalized) {
59
- return "#151821";
60
- }
61
- const r = parseInt(normalized.slice(1, 3), 16);
62
- const g = parseInt(normalized.slice(3, 5), 16);
63
- const b = parseInt(normalized.slice(5, 7), 16);
64
- const yiq = (r * 299 + g * 587 + b * 114) / 1000;
65
- return yiq >= 145 ? "#151821" : "#F7FAFC";
43
+ function getReadableTextColor(hex) {
44
+ const normalized = normalizeHex(hex);
45
+ if (!normalized) {
46
+ return "#151821";
47
+ }
48
+ const r = parseInt(normalized.slice(1, 3), 16);
49
+ const g = parseInt(normalized.slice(3, 5), 16);
50
+ const b = parseInt(normalized.slice(5, 7), 16);
51
+ const yiq = (r * 299 + g * 587 + b * 114) / 1000;
52
+ return yiq >= 145 ? "#151821" : "#F7FAFC";
66
53
  }
54
+
55
+ export { darken, getReadableTextColor, invertAndGrayscaleHex, isValidHex, normalizeHex, rgbToHex };
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@themodcraft/core-ui",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
7
  "type": "module",
8
- "files": ["dist"],
9
- "sideEffects": ["./dist/styles/*.css"],
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "sideEffects": [
12
+ "./dist/**/*.css"
13
+ ],
10
14
  "exports": {
11
15
  ".": {
12
16
  "types": "./dist/index.d.ts",
@@ -20,10 +24,6 @@
20
24
  "prepack": "npm run build",
21
25
  "typecheck": "tsc -p tsconfig.json --noEmit"
22
26
  },
23
- "dependencies": {
24
- "@emotion/react": "^11.14.0",
25
- "@emotion/styled": "^11.14.1"
26
- },
27
27
  "peerDependencies": {
28
28
  "react": "^19.0.0",
29
29
  "react-dom": "^19.0.0"
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};