ecmc-design-core 0.0.3 → 0.0.5

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.
@@ -1,13 +1,23 @@
1
+ <!--
2
+ @component
3
+ # Button
4
+
5
+ A foundational button component supporting multiple visual variants.
6
+
7
+ @param {Snippet} [children] - The content to be rendered inside the button
8
+ @param {'primary' | 'secondary' | 'disabled'} [variant='primary'] - Visual variant: 'primary' (main action with --red-500/600/700), 'secondary' (alternative with --neutral-100/300/400), 'disabled' (non-interactive with reduced opacity)
9
+ @param {(event: MouseEvent) => void} [onclick] - Click handler for button interactions
10
+ -->
1
11
  <script lang="ts">
2
- import Centered from '../container/sub/centered.container.svelte';
3
- import Text from '../text/Text.svelte';
4
12
  import { cn } from '../../utils/cn.js';
13
+ import { Centered, Text } from '../../index.js';
14
+
5
15
  import { buttonVariantClasses, defaultProps } from './constants.js';
6
16
  import type { ButtonProps } from './types.js';
7
17
 
8
18
  let { children, onclick, variant = defaultProps.variant! }: ButtonProps = $props();
9
19
 
10
- let computedClasses = $derived(cn(buttonVariantClasses[variant]));
20
+ let computedClasses = $derived(cn('ecmc', 'ecmc-button', buttonVariantClasses[variant]));
11
21
  </script>
12
22
 
13
23
  <button class={computedClasses} disabled={variant === 'disabled'} {onclick}>
@@ -21,39 +31,39 @@
21
31
  <style>
22
32
  button {
23
33
  border: none;
24
- border-radius: var(--rounding-size-1);
34
+ border-radius: var(--ecmc-rounding-size-1);
25
35
  cursor: pointer;
26
36
  }
27
37
 
28
38
  .button--primary {
29
- background-color: var(--primary-600);
39
+ background-color: var(--ecmc-primary-600);
30
40
  color: var(--neutral-100);
31
41
  }
32
42
 
33
43
  .button--primary:hover {
34
- background-color: var(--primary-700);
44
+ background-color: var(--ecmc-primary-700);
35
45
  }
36
46
 
37
47
  .button--primary:active {
38
- background-color: var(--primary-900);
48
+ background-color: var(--ecmc-primary-900);
39
49
  }
40
50
 
41
51
  .button--secondary {
42
- background-color: var(--neutral-400);
52
+ background-color: var(--ecmc-neutral-400);
43
53
  color: var(--neutral-100);
44
54
  }
45
55
 
46
56
  .button--secondary:hover {
47
- background-color: var(--neutral-500);
57
+ background-color: var(--ecmc-neutral-500);
48
58
  color: var(--neutral-100);
49
59
  }
50
60
 
51
61
  .button--secondary:active {
52
- background-color: var(--neutral-600);
62
+ background-color: var(--ecmc-neutral-600);
53
63
  }
54
64
 
55
65
  .button--disabled {
56
- background-color: var(--neutral-300);
66
+ background-color: var(--ecmc-neutral-300);
57
67
  color: var(--neutral-600);
58
68
  cursor: not-allowed;
59
69
  opacity: 0.6;
@@ -1,4 +1,13 @@
1
1
  import type { ButtonProps } from './types.js';
2
+ /**
3
+ * # Button
4
+ *
5
+ * A foundational button component supporting multiple visual variants.
6
+ *
7
+ * @param {Snippet} [children] - The content to be rendered inside the button
8
+ * @param {'primary' | 'secondary' | 'disabled'} [variant='primary'] - Visual variant: 'primary' (main action with --red-500/600/700), 'secondary' (alternative with --neutral-100/300/400), 'disabled' (non-interactive with reduced opacity)
9
+ * @param {(event: MouseEvent) => void} [onclick] - Click handler for button interactions
10
+ */
2
11
  declare const Button: import("svelte").Component<ButtonProps, {}, "">;
3
12
  type Button = ReturnType<typeof Button>;
4
13
  export default Button;
@@ -1,7 +1,20 @@
1
+ <!--
2
+ @component
3
+ # Container
4
+
5
+ A flexible container component with real-time DOM metrics tracking and extensive styling options.
6
+
7
+ @param {Snippet} [children] - The content to be rendered inside the container
8
+ @param {'none' | 'xsm' | 'sm' | 'md' | 'lg' | 'xl'} [padding='none'] - Padding size mapped to CSS --spacing-* variables
9
+ @param {boolean} [fill=false] - Whether to make the container fill its parent dimensions (sets width and height to 100%)
10
+ @param {boolean} [bg=false] - Whether to apply a background color (neutral-200 in light mode, neutral-800 in dark mode)
11
+ @param {boolean} [rounding=false] - Whether to apply border radius using var(--rounding-size-1) which is 5px
12
+ @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics (dimensions, position, scroll state)
13
+ -->
1
14
  <script lang="ts">
2
15
  import { cn } from '../../utils/cn.js';
3
- import type { ContainerProps } from './types.js';
4
16
  import { defaultProps, paddingClasses } from './constants.js';
17
+ import type { ContainerProps } from './types.js';
5
18
 
6
19
  // Props with defaults
7
20
  let {
@@ -16,6 +29,8 @@
16
29
 
17
30
  let computedClasses = $derived(
18
31
  cn(
32
+ 'ecmc',
33
+ 'ecmc-container',
19
34
  paddingClasses[padding],
20
35
  fill ? 'container--fill' : '',
21
36
  bg ? 'container--bg' : '',
@@ -78,27 +93,27 @@
78
93
 
79
94
  <style>
80
95
  .container--padding-none {
81
- padding: var(--spacing-none);
96
+ padding: var(--ecmc-spacing-none);
82
97
  }
83
98
 
84
99
  .container--padding-xsm {
85
- padding: var(--spacing-xsm);
100
+ padding: var(--ecmc-spacing-xsm);
86
101
  }
87
102
 
88
103
  .container--padding-sm {
89
- padding: var(--spacing-sm);
104
+ padding: var(--ecmc-spacing-sm);
90
105
  }
91
106
 
92
107
  .container--padding-md {
93
- padding: var(--spacing-md);
108
+ padding: var(--ecmc-spacing-md);
94
109
  }
95
110
 
96
111
  .container--padding-lg {
97
- padding: var(--spacing-lg);
112
+ padding: var(--ecmc-spacing-lg);
98
113
  }
99
114
 
100
115
  .container--padding-xl {
101
- padding: var(--spacing-xl);
116
+ padding: var(--ecmc-spacing-xl);
102
117
  }
103
118
 
104
119
  .container--fill {
@@ -107,10 +122,10 @@
107
122
  }
108
123
 
109
124
  .container--bg {
110
- background-color: light-dark(var(--neutral-200), var(--neutral-800));
125
+ background-color: light-dark(var(--ecmc-neutral-200), var(--ecmc-neutral-800));
111
126
  }
112
127
 
113
128
  .container--rounding {
114
- border-radius: var(--rounding-size-1);
129
+ border-radius: var(--ecmc-rounding-size-1);
115
130
  }
116
131
  </style>
@@ -1,4 +1,16 @@
1
1
  import type { ContainerProps } from './types.js';
2
+ /**
3
+ * # Container
4
+ *
5
+ * A flexible container component with real-time DOM metrics tracking and extensive styling options.
6
+ *
7
+ * @param {Snippet} [children] - The content to be rendered inside the container
8
+ * @param {'none' | 'xsm' | 'sm' | 'md' | 'lg' | 'xl'} [padding='none'] - Padding size mapped to CSS --spacing-* variables
9
+ * @param {boolean} [fill=false] - Whether to make the container fill its parent dimensions (sets width and height to 100%)
10
+ * @param {boolean} [bg=false] - Whether to apply a background color (neutral-200 in light mode, neutral-800 in dark mode)
11
+ * @param {boolean} [rounding=false] - Whether to apply border radius using var(--rounding-size-1) which is 5px
12
+ * @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics (dimensions, position, scroll state)
13
+ */
2
14
  declare const Container: import("svelte").Component<ContainerProps, {}, "metrics">;
3
15
  type Container = ReturnType<typeof Container>;
4
16
  export default Container;
@@ -20,7 +20,7 @@
20
20
  <Container bind:metrics {...containerProps}>
21
21
  <div
22
22
  class="box"
23
- style="gap: var(--spacing-{gap}); align-items: {align}; justify-content: {justify}; flex-wrap: {flexWrap}; flex-direction: {flexDirection};"
23
+ style="gap: var(--ecmc-spacing-{gap}); align-items: {align}; justify-content: {justify}; flex-wrap: {flexWrap}; flex-direction: {flexDirection};"
24
24
  >
25
25
  {@render children?.()}
26
26
  </div>
@@ -1,3 +1,15 @@
1
+ <!--
2
+ @component
3
+ # Centered
4
+
5
+ A container component that centers content horizontally and/or vertically using flexbox.
6
+
7
+ @param {Snippet} [children] - The content to be rendered inside the centered container
8
+ @param {boolean} [horizontal=true] - Whether to center content horizontally
9
+ @param {boolean} [vertical=true] - Whether to center content vertically
10
+ @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics
11
+ @param {ContainerProps} [...containerProps] - All standard Container props (padding, fill, bg, rounding, etc.)
12
+ -->
1
13
  <script lang="ts">
2
14
  import Container from '../Container.svelte';
3
15
  import type { CenteredProps } from '../types.js';
@@ -1,4 +1,15 @@
1
1
  import type { CenteredProps } from '../types.js';
2
+ /**
3
+ * # Centered
4
+ *
5
+ * A container component that centers content horizontally and/or vertically using flexbox.
6
+ *
7
+ * @param {Snippet} [children] - The content to be rendered inside the centered container
8
+ * @param {boolean} [horizontal=true] - Whether to center content horizontally
9
+ * @param {boolean} [vertical=true] - Whether to center content vertically
10
+ * @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics
11
+ * @param {ContainerProps} [...containerProps] - All standard Container props (padding, fill, bg, rounding, etc.)
12
+ */
2
13
  declare const Centered: import("svelte").Component<CenteredProps, {}, "metrics">;
3
14
  type Centered = ReturnType<typeof Centered>;
4
15
  export default Centered;
@@ -1,3 +1,16 @@
1
+ <!--
2
+ @component
3
+ # GridBox
4
+
5
+ A CSS Grid container with customizable columns, gap spacing, and auto-flow behavior.
6
+
7
+ @param {Snippet} [children] - The content to be rendered inside the grid box
8
+ @param {number | string} [columns=2] - Number of columns (e.g., 3 → repeat(3, 1fr)) or custom grid-template-columns value
9
+ @param {'none' | 'xsm' | 'sm' | 'md' | 'lg' | 'xl'} [gap='md'] - Gap spacing between grid items mapped to CSS --spacing-* variables
10
+ @param {'row' | 'column' | 'dense' | 'row dense' | 'column dense'} [autoFlow='row'] - Controls how auto-placed items flow into the grid
11
+ @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics
12
+ @param {ContainerProps} [...containerProps] - All standard Container props (padding, fill, bg, rounding, etc.)
13
+ -->
1
14
  <script lang="ts">
2
15
  import Container from '../Container.svelte';
3
16
  import type { GridBoxProps } from '../types.js';
@@ -19,7 +32,7 @@
19
32
  <Container bind:metrics {...containerProps}>
20
33
  <div
21
34
  class="gridbox"
22
- style="grid-template-columns: {gridTemplateColumns}; gap: var(--spacing-{gap}); grid-auto-flow: {autoFlow};"
35
+ style="grid-template-columns: {gridTemplateColumns}; gap: var(--ecmc-spacing-{gap}); grid-auto-flow: {autoFlow};"
23
36
  >
24
37
  {@render children?.()}
25
38
  </div>
@@ -1,4 +1,16 @@
1
1
  import type { GridBoxProps } from '../types.js';
2
+ /**
3
+ * # GridBox
4
+ *
5
+ * A CSS Grid container with customizable columns, gap spacing, and auto-flow behavior.
6
+ *
7
+ * @param {Snippet} [children] - The content to be rendered inside the grid box
8
+ * @param {number | string} [columns=2] - Number of columns (e.g., 3 → repeat(3, 1fr)) or custom grid-template-columns value
9
+ * @param {'none' | 'xsm' | 'sm' | 'md' | 'lg' | 'xl'} [gap='md'] - Gap spacing between grid items mapped to CSS --spacing-* variables
10
+ * @param {'row' | 'column' | 'dense' | 'row dense' | 'column dense'} [autoFlow='row'] - Controls how auto-placed items flow into the grid
11
+ * @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics
12
+ * @param {ContainerProps} [...containerProps] - All standard Container props (padding, fill, bg, rounding, etc.)
13
+ */
2
14
  declare const Gridbox: import("svelte").Component<GridBoxProps, {}, "metrics">;
3
15
  type Gridbox = ReturnType<typeof Gridbox>;
4
16
  export default Gridbox;
@@ -1,3 +1,17 @@
1
+ <!--
2
+ @component
3
+ # HBox
4
+
5
+ A horizontal flexbox container (row layout) with customizable gap, alignment, and wrapping.
6
+
7
+ @param {Snippet} [children] - The content to be rendered inside the horizontal box
8
+ @param {'none' | 'xsm' | 'sm' | 'md' | 'lg' | 'xl'} [gap] - Gap spacing between flex items mapped to CSS --spacing-* variables
9
+ @param {'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'} [align='flex-start'] - Cross-axis alignment of flex items
10
+ @param {'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'} [justify='flex-start'] - Main-axis justification of flex items
11
+ @param {boolean} [wrap=false] - Whether flex items should wrap to multiple lines
12
+ @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics
13
+ @param {ContainerProps} [...props] - All standard Container props (padding, fill, bg, rounding, etc.)
14
+ -->
1
15
  <script lang="ts">
2
16
  import Box from './box.container.svelte';
3
17
  import type { BoxProps } from '../types.js';
@@ -1,4 +1,17 @@
1
1
  import type { BoxProps } from '../types.js';
2
+ /**
3
+ * # HBox
4
+ *
5
+ * A horizontal flexbox container (row layout) with customizable gap, alignment, and wrapping.
6
+ *
7
+ * @param {Snippet} [children] - The content to be rendered inside the horizontal box
8
+ * @param {'none' | 'xsm' | 'sm' | 'md' | 'lg' | 'xl'} [gap] - Gap spacing between flex items mapped to CSS --spacing-* variables
9
+ * @param {'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'} [align='flex-start'] - Cross-axis alignment of flex items
10
+ * @param {'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'} [justify='flex-start'] - Main-axis justification of flex items
11
+ * @param {boolean} [wrap=false] - Whether flex items should wrap to multiple lines
12
+ * @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics
13
+ * @param {ContainerProps} [...props] - All standard Container props (padding, fill, bg, rounding, etc.)
14
+ */
2
15
  declare const Hbox: import("svelte").Component<BoxProps, {}, "metrics">;
3
16
  type Hbox = ReturnType<typeof Hbox>;
4
17
  export default Hbox;
@@ -1,3 +1,17 @@
1
+ <!--
2
+ @component
3
+ # VBox
4
+
5
+ A vertical flexbox container (column layout) with customizable gap, alignment, and wrapping.
6
+
7
+ @param {Snippet} [children] - The content to be rendered inside the vertical box
8
+ @param {'none' | 'xsm' | 'sm' | 'md' | 'lg' | 'xl'} [gap] - Gap spacing between flex items mapped to CSS --spacing-* variables
9
+ @param {'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'} [align='flex-start'] - Cross-axis alignment of flex items
10
+ @param {'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'} [justify='flex-start'] - Main-axis justification of flex items
11
+ @param {boolean} [wrap=false] - Whether flex items should wrap to multiple lines
12
+ @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics
13
+ @param {ContainerProps} [...props] - All standard Container props (padding, fill, bg, rounding, etc.)
14
+ -->
1
15
  <script lang="ts">
2
16
  import Box from './box.container.svelte';
3
17
  import type { BoxProps } from '../types.js';
@@ -1,4 +1,17 @@
1
1
  import type { BoxProps } from '../types.js';
2
+ /**
3
+ * # VBox
4
+ *
5
+ * A vertical flexbox container (column layout) with customizable gap, alignment, and wrapping.
6
+ *
7
+ * @param {Snippet} [children] - The content to be rendered inside the vertical box
8
+ * @param {'none' | 'xsm' | 'sm' | 'md' | 'lg' | 'xl'} [gap] - Gap spacing between flex items mapped to CSS --spacing-* variables
9
+ * @param {'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'} [align='flex-start'] - Cross-axis alignment of flex items
10
+ * @param {'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'} [justify='flex-start'] - Main-axis justification of flex items
11
+ * @param {boolean} [wrap=false] - Whether flex items should wrap to multiple lines
12
+ * @param {ContainerMetrics} [metrics] - Bindable prop to track real-time container element metrics
13
+ * @param {ContainerProps} [...props] - All standard Container props (padding, fill, bg, rounding, etc.)
14
+ */
2
15
  declare const Vbox: import("svelte").Component<BoxProps, {}, "metrics">;
3
16
  type Vbox = ReturnType<typeof Vbox>;
4
17
  export default Vbox;
@@ -1,3 +1,17 @@
1
+ <!--
2
+ @component
3
+ # Input
4
+
5
+ A form input field with label support, multiple input types, and responsive label positioning.
6
+ Automatically repositions labels on small screens (< 640px) for better mobile UX.
7
+
8
+ @param {'text' | 'email' | 'password'} [type='text'] - Type of input field: 'text' (standard), 'email' (with validation), 'password' (masked characters)
9
+ @param {string} [label=''] - Label text displayed above or beside the input, also used for aria-label accessibility
10
+ @param {boolean} [labelLeft=false] - Position label to the left (horizontal layout on desktop, automatically reverts to vertical on screens < 640px)
11
+ @param {string} [placeholder=''] - Placeholder text shown when the input is empty
12
+ @param {string} value - The current value of the input field (bindable using bind:value)
13
+ @param {string} [id] - HTML id attribute for the input element, auto-generated from label if not provided
14
+ -->
1
15
  <script lang="ts">
2
16
  import { HBox, VBox, Centered } from '../../index.js';
3
17
  import Text from '../text/Text.svelte';
@@ -45,31 +59,33 @@
45
59
  />
46
60
  {/snippet}
47
61
 
48
- {#if effectiveLabelLeft}
49
- <HBox gap="xsm">
50
- {@render contents()}
51
- </HBox>
52
- {:else}
53
- <VBox gap="none">
54
- {@render contents()}
55
- </VBox>
56
- {/if}
62
+ <div class="ecmc ecmc-input">
63
+ {#if effectiveLabelLeft}
64
+ <HBox gap="xsm">
65
+ {@render contents()}
66
+ </HBox>
67
+ {:else}
68
+ <VBox gap="none">
69
+ {@render contents()}
70
+ </VBox>
71
+ {/if}
72
+ </div>
57
73
 
58
74
  <style>
59
75
  input {
60
- padding: var(--spacing-xsm);
61
- background-color: light-dark(var(--neutral-300), var(--neutral-700));
62
- border: 1px solid light-dark(var(--neutral-300), var(--neutral-700));
76
+ padding: var(--ecmc-spacing-xsm);
77
+ background-color: light-dark(var(--ecmc-neutral-300), var(--ecmc-neutral-700));
78
+ border: 1px solid light-dark(var(--ecmc-neutral-300), var(--ecmc-neutral-700));
63
79
  outline: none;
64
80
  width: 100%;
65
81
  }
66
82
 
67
83
  input::placeholder {
68
- color: light-dark(var(--neutral-500), var(--neutral-400));
84
+ color: light-dark(var(--ecmc-neutral-500), var(--ecmc-neutral-400));
69
85
  opacity: 0.7;
70
86
  }
71
87
 
72
88
  input:focus {
73
- border-color: light-dark(var(--neutral-900), var(--neutral-300));
89
+ border-color: light-dark(var(--ecmc-neutral-900), var(--ecmc-neutral-300));
74
90
  }
75
91
  </style>
@@ -1,4 +1,17 @@
1
1
  import type { InputProps } from './types.js';
2
+ /**
3
+ * # Input
4
+ *
5
+ * A form input field with label support, multiple input types, and responsive label positioning.
6
+ * Automatically repositions labels on small screens (< 640px) for better mobile UX.
7
+ *
8
+ * @param {'text' | 'email' | 'password'} [type='text'] - Type of input field: 'text' (standard), 'email' (with validation), 'password' (masked characters)
9
+ * @param {string} [label=''] - Label text displayed above or beside the input, also used for aria-label accessibility
10
+ * @param {boolean} [labelLeft=false] - Position label to the left (horizontal layout on desktop, automatically reverts to vertical on screens < 640px)
11
+ * @param {string} [placeholder=''] - Placeholder text shown when the input is empty
12
+ * @param {string} value - The current value of the input field (bindable using bind:value)
13
+ * @param {string} [id] - HTML id attribute for the input element, auto-generated from label if not provided
14
+ */
2
15
  declare const Input: import("svelte").Component<InputProps, {}, "value">;
3
16
  type Input = ReturnType<typeof Input>;
4
17
  export default Input;
@@ -1,3 +1,14 @@
1
+ <!--
2
+ @component
3
+ # Kbd
4
+
5
+ Represents keyboard keys or shortcuts with visual styling that resembles physical keyboard keys.
6
+ Useful for displaying keyboard shortcuts, hotkeys, or keyboard-related instructions.
7
+
8
+ @param {Snippet} [children] - The content to be rendered inside the kbd element (typically key labels like "Ctrl", "⌘", etc.)
9
+ @param {'small' | 'medium' | 'large'} [size='small'] - Size variant: 'small' (compact for inline usage), 'medium' (standard), 'large' (emphasis)
10
+ @param {HTMLAttributes<HTMLElement>} [...restProps] - All standard HTML kbd element attributes
11
+ -->
1
12
  <script lang="ts">
2
13
  import { cn } from '../../utils/cn.js';
3
14
  import type { KbdProps } from './types.js';
@@ -6,7 +17,7 @@
6
17
 
7
18
  let { children, size = defaultProps.size!, ...restProps }: KbdProps = $props();
8
19
 
9
- let computedClasses = $derived(cn(kbdSizeClasses[size]));
20
+ let computedClasses = $derived(cn('ecmc', 'ecmc-kbd', kbdSizeClasses[size]));
10
21
  </script>
11
22
 
12
23
  <Centered padding="none" fill={false}>
@@ -17,27 +28,27 @@
17
28
 
18
29
  <style>
19
30
  kbd {
20
- background-color: light-dark(var(--neutral-100), var(--neutral-700));
21
- color: light-dark(var(--neutral-900), var(--neutral-100));
22
- border-color: light-dark(var(--neutral-300), var(--neutral-500));
31
+ background-color: light-dark(var(--ecmc-neutral-100), var(--ecmc-neutral-700));
32
+ color: light-dark(var(--ecmc-neutral-900), var(--ecmc-neutral-100));
33
+ border-color: light-dark(var(--ecmc-neutral-300), var(--ecmc-neutral-500));
23
34
  display: inline-block;
24
35
  line-height: 1;
25
- border-radius: var(--rounding-size-1);
36
+ border-radius: var(--ecmc-rounding-size-1);
26
37
  border: 1px solid;
27
38
  }
28
39
 
29
40
  .kbd--small {
30
- padding: calc(var(--spacing-xsm) * 0.5) var(--spacing-xsm);
31
- font-size: var(--font-size-0);
41
+ padding: calc(var(--ecmc-spacing-xsm) * 0.5) var(--ecmc-spacing-xsm);
42
+ font-size: var(--ecmc-font-size-0);
32
43
  }
33
44
 
34
45
  .kbd--medium {
35
- padding: var(--spacing-xsm) var(--spacing-sm);
36
- font-size: var(--font-size-1);
46
+ padding: var(--ecmc-spacing-xsm) var(--ecmc-spacing-sm);
47
+ font-size: var(--ecmc-font-size-1);
37
48
  }
38
49
 
39
50
  .kbd--large {
40
- padding: var(--spacing-sm) var(--spacing-md);
41
- font-size: var(--font-size-2);
51
+ padding: var(--ecmc-spacing-sm) var(--ecmc-spacing-md);
52
+ font-size: var(--ecmc-font-size-2);
42
53
  }
43
54
  </style>
@@ -1,4 +1,14 @@
1
1
  import type { KbdProps } from './types.js';
2
+ /**
3
+ * # Kbd
4
+ *
5
+ * Represents keyboard keys or shortcuts with visual styling that resembles physical keyboard keys.
6
+ * Useful for displaying keyboard shortcuts, hotkeys, or keyboard-related instructions.
7
+ *
8
+ * @param {Snippet} [children] - The content to be rendered inside the kbd element (typically key labels like "Ctrl", "⌘", etc.)
9
+ * @param {'small' | 'medium' | 'large'} [size='small'] - Size variant: 'small' (compact for inline usage), 'medium' (standard), 'large' (emphasis)
10
+ * @param {HTMLAttributes<HTMLElement>} [...restProps] - All standard HTML kbd element attributes
11
+ */
2
12
  declare const Kbd: import("svelte").Component<KbdProps, {}, "">;
3
13
  type Kbd = ReturnType<typeof Kbd>;
4
14
  export default Kbd;
@@ -1,3 +1,17 @@
1
+ <!--
2
+ @component
3
+ # Text
4
+
5
+ Provides typography with various size variants, alignment, and styling options.
6
+ Renders as block-level div or inline span based on the inline prop.
7
+
8
+ @param {Snippet} [children] - The content to be rendered inside the text element
9
+ @param {'headline' | 'subtitle' | 'body' | 'bodyPlus' | 'half'} [variant='body'] - Text variant: 'headline' (3rem/48px), 'subtitle' (2.5rem/40px), 'body' (1rem/16px), 'bodyPlus' (1.2rem/19.2px)
10
+ @param {boolean} [italic=false] - Whether the text should be rendered in italic style
11
+ @param {boolean} [inline=false] - Whether to render as inline span (true) or block-level div (false)
12
+ @param {'left' | 'center' | 'right'} [align='left'] - Horizontal text alignment
13
+ @param {HTMLAttributes<HTMLElement>} [...restProps] - All standard HTML element attributes
14
+ -->
1
15
  <script lang="ts">
2
16
  import { cn } from '../../utils/cn.js';
3
17
  import type { TextProps } from './types.js';
@@ -14,7 +28,13 @@
14
28
  }: TextProps = $props();
15
29
 
16
30
  let computedClasses = $derived(
17
- cn(textAlignClasses[align], textVariantClasses[variant], italic ? 'text--italic' : '')
31
+ cn(
32
+ 'ecmc',
33
+ 'ecmc-text',
34
+ textAlignClasses[align],
35
+ textVariantClasses[variant],
36
+ italic ? 'text--italic' : ''
37
+ )
18
38
  );
19
39
  </script>
20
40
 
@@ -31,27 +51,27 @@
31
51
  <style>
32
52
  .text--headline {
33
53
  font-weight: 700;
34
- font-size: var(--font-size-4);
54
+ font-size: var(--ecmc-font-size-4);
35
55
  }
36
56
 
37
57
  .text--subtitle {
38
58
  font-weight: 500;
39
- font-size: var(--font-size-3);
59
+ font-size: var(--ecmc-font-size-3);
40
60
  }
41
61
 
42
62
  .text--body-plus {
43
63
  font-weight: 300;
44
- font-size: var(--font-size-2);
64
+ font-size: var(--ecmc-font-size-2);
45
65
  }
46
66
 
47
67
  .text--body {
48
68
  font-weight: 300;
49
- font-size: var(--font-size-1);
69
+ font-size: var(--ecmc-font-size-1);
50
70
  }
51
71
 
52
72
  .text--half {
53
73
  font-weight: 100;
54
- font-size: var(--font-size-0);
74
+ font-size: var(--ecmc-font-size-0);
55
75
  }
56
76
 
57
77
  .text--italic {
@@ -1,4 +1,17 @@
1
1
  import type { TextProps } from './types.js';
2
+ /**
3
+ * # Text
4
+ *
5
+ * Provides typography with various size variants, alignment, and styling options.
6
+ * Renders as block-level div or inline span based on the inline prop.
7
+ *
8
+ * @param {Snippet} [children] - The content to be rendered inside the text element
9
+ * @param {'headline' | 'subtitle' | 'body' | 'bodyPlus' | 'half'} [variant='body'] - Text variant: 'headline' (3rem/48px), 'subtitle' (2.5rem/40px), 'body' (1rem/16px), 'bodyPlus' (1.2rem/19.2px)
10
+ * @param {boolean} [italic=false] - Whether the text should be rendered in italic style
11
+ * @param {boolean} [inline=false] - Whether to render as inline span (true) or block-level div (false)
12
+ * @param {'left' | 'center' | 'right'} [align='left'] - Horizontal text alignment
13
+ * @param {HTMLAttributes<HTMLElement>} [...restProps] - All standard HTML element attributes
14
+ */
2
15
  declare const Text: import("svelte").Component<TextProps, {}, "">;
3
16
  type Text = ReturnType<typeof Text>;
4
17
  export default Text;
@@ -1,20 +1,14 @@
1
1
  @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap');
2
2
 
3
- *,
4
- *::before,
5
- *::after {
3
+ .ecmc,
4
+ .ecmc::before,
5
+ .ecmc::after {
6
6
  box-sizing: border-box;
7
7
  }
8
8
 
9
- * {
9
+ .ecmc {
10
10
  margin: 0;
11
11
  padding: 0;
12
- font: inherit;
13
- }
14
-
15
- body {
16
- min-height: 100vh;
17
- background-color: light-dark(var(--neutral-100), var(--neutral-900));
18
12
  }
19
13
 
20
14
  html {
@@ -30,97 +24,100 @@ video {
30
24
  }
31
25
 
32
26
  /* ---- ATOMS ---- */
33
-
34
27
  /* Font Atoms */
35
- :root {
36
- font-family: 'Roboto Mono', monospace;
28
+ .ecmc {
29
+ --ecmc-font-root: 16px;
30
+ --ecmc-font-size-0: 0.7em;
31
+ --ecmc-font-size-1: 1em;
32
+ --ecmc-font-size-2: 1.2em;
33
+ --ecmc-font-size-3: 2.5em;
34
+ --ecmc-font-size-4: 3em;
35
+
36
+ --ecmc-font-face-main: 'Roboto Mono', monospace;
37
+ --ecmc-font-face-weight-main: 300;
38
+
39
+ font-family: var(--ecmc-font-face-main);
40
+ font-weight: var(--ecmc-font-face-weight-main);
41
+ font-size: var(--ecmc-font-root);
42
+ color: light-dark(var(--neutral-900), var(--neutral-100));
37
43
  font-optical-sizing: auto;
38
- font-weight: 300;
39
44
  font-style: normal;
40
- font-size: 16px;
41
- color: light-dark(var(--neutral-900), var(--neutral-100));
42
-
43
- --font-size-0: 0.7rem;
44
- --font-size-1: 1rem;
45
- --font-size-2: 1.2rem;
46
- --font-size-3: 2.5rem;
47
- --font-size-4: 3rem;
48
45
  }
49
46
 
50
47
  /* Colour Atoms */
51
- :root {
52
- --neutral-50: #f5f7fa;
53
- --neutral-100: #dfe2e6;
54
- --neutral-200: #c0c5ce;
55
- --neutral-300: #a7adba;
56
- --neutral-400: #65737e;
57
- --neutral-500: #4f5b66;
58
- --neutral-600: #343d46;
59
- --neutral-700: #23292f;
60
- --neutral-800: #1a1e23;
61
- --neutral-900: #111417;
62
-
63
- --primary-900: #660708;
64
- --primary-700: #a4161a;
65
- --primary-600: #ba181b;
66
- --primary-500: #e5383b;
48
+ .ecmc {
49
+ --ecmc-neutral-50: #f5f7fa;
50
+ --ecmc-neutral-100: #dfe2e6;
51
+ --ecmc-neutral-200: #c0c5ce;
52
+ --ecmc-neutral-300: #a7adba;
53
+ --ecmc-neutral-400: #65737e;
54
+ --ecmc-neutral-500: #4f5b66;
55
+ --ecmc-neutral-600: #343d46;
56
+ --ecmc-neutral-700: #23292f;
57
+ --ecmc-neutral-800: #1a1e23;
58
+ --ecmc-neutral-900: #111417;
59
+
60
+ --ecmc-primary-900: #660708;
61
+ --ecmc-primary-700: #a4161a;
62
+ --ecmc-primary-600: #ba181b;
63
+ --ecmc-primary-500: #e5383b;
67
64
  }
68
65
 
69
66
  /* Spacing Atoms */
70
- :root {
71
- --spacing-none: 0rem;
72
- --spacing-xsm: 0.5rem;
73
- --spacing-sm: 1rem;
74
- --spacing-md: 1.5rem;
75
- --spacing-lg: 2rem;
76
- --spacing-xl: 3rem;
67
+ .ecmc {
68
+ --ecmc-spacing-none: 0em;
69
+ --ecmc-spacing-xsm: 0.5em;
70
+ --ecmc-spacing-sm: 1em;
71
+ --ecmc-spacing-md: 1.5em;
72
+ --ecmc-spacing-lg: 2em;
73
+ --ecmc-spacing-xl: 3em;
77
74
  }
78
75
 
79
76
  /* Rounding Atoms */
80
- :root {
81
- --rounding-size-1: 5px;
82
- --rounding-size-2: 15px;
77
+ .ecmc {
78
+ --ecmc-rounding-size-1: 5px;
79
+ --ecmc-rounding-size-2: 15px;
83
80
  }
84
81
 
85
82
  /* responsive breakpoints (mobile-first) */
86
83
  @media (min-width: 480px) {
87
- :root {
88
- --font-size-2: 1.1rem;
89
- --spacing-md: 1.25rem;
84
+ .ecmc {
85
+ --ecmc-font-size-2: 1.1em;
86
+ --ecmc-spacing-md: 1.25em;
90
87
  }
91
88
  }
92
89
 
93
90
  @media (min-width: 640px) {
94
- :root {
95
- --font-size-3: 2.3rem;
96
- --spacing-lg: 2.25rem;
91
+ .ecmc {
92
+ --ecmc-font-size-3: 2.3em;
93
+ --ecmc-spacing-lg: 2.25em;
97
94
  }
98
95
  }
99
96
 
100
97
  @media (min-width: 768px) {
101
- :root {
102
- --font-size-2: 1.2rem;
103
- --font-size-3: 2.5rem;
104
- --spacing-xl: 3.25rem;
98
+ .ecmc {
99
+ --ecmc-font-size-2: 1.2em;
100
+ --ecmc-font-size-3: 2.5em;
101
+ --ecmc-spacing-xl: 3.25em;
105
102
  }
106
103
  }
107
104
 
108
105
  @media (min-width: 1024px) {
109
- :root {
110
- --font-size-4: 3.25rem;
106
+ .ecmc {
107
+ --ecmc-font-size-4: 3.25em;
111
108
  }
112
109
  }
113
110
 
114
111
  @media (min-width: 1280px) {
115
- :root {
116
- --font-size-3: 2.7rem;
117
- --font-size-4: 3.5rem;
112
+ .ecmc {
113
+ --ecmc-font-size-3: 2.7em;
114
+ --ecmc-font-size-4: 3.5em;
118
115
  }
119
116
  }
120
117
 
121
118
  @media (min-width: 1536px) {
122
- :root {
123
- --font-size-3: 2.9rem;
124
- --font-size-4: 3.75rem;
119
+ .ecmc {
120
+ --ecmc-font-size-3: 2.9em;
121
+ --ecmc-font-size-4: 3.75em;
125
122
  }
126
123
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "ecmc-design-core",
3
3
  "description": "Atoms and molecules for ecmc design system",
4
4
  "license": "MIT",
5
- "version": "0.0.3",
5
+ "version": "0.0.5",
6
6
  "author": {
7
7
  "name": "Arad Fadaei",
8
8
  "url": "https://www.fadaei.dev"
@@ -40,7 +40,8 @@
40
40
  ".": {
41
41
  "types": "./dist/index.d.ts",
42
42
  "svelte": "./dist/index.js"
43
- }
43
+ },
44
+ "./ecmc.css": "./dist/utils/ecmc.css"
44
45
  },
45
46
  "peerDependencies": {
46
47
  "svelte": "^5.0.0"