ecmc-design-core 0.0.1

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 (37) hide show
  1. package/README.md +55 -0
  2. package/dist/atoms/button/Button.svelte +61 -0
  3. package/dist/atoms/button/Button.svelte.d.ts +4 -0
  4. package/dist/atoms/button/constants.d.ts +7 -0
  5. package/dist/atoms/button/constants.js +8 -0
  6. package/dist/atoms/button/types.d.ts +35 -0
  7. package/dist/atoms/container/Container.svelte +106 -0
  8. package/dist/atoms/container/Container.svelte.d.ts +4 -0
  9. package/dist/atoms/container/constants.d.ts +16 -0
  10. package/dist/atoms/container/constants.js +19 -0
  11. package/dist/atoms/container/sub/box.container.svelte +33 -0
  12. package/dist/atoms/container/sub/box.container.svelte.d.ts +4 -0
  13. package/dist/atoms/container/sub/centered.container.svelte +28 -0
  14. package/dist/atoms/container/sub/centered.container.svelte.d.ts +4 -0
  15. package/dist/atoms/container/sub/gridbox.container.svelte +32 -0
  16. package/dist/atoms/container/sub/gridbox.container.svelte.d.ts +4 -0
  17. package/dist/atoms/container/sub/hbox.container.svelte +10 -0
  18. package/dist/atoms/container/sub/hbox.container.svelte.d.ts +4 -0
  19. package/dist/atoms/container/sub/vbox.container.svelte +10 -0
  20. package/dist/atoms/container/sub/vbox.container.svelte.d.ts +4 -0
  21. package/dist/atoms/container/types.d.ts +252 -0
  22. package/dist/atoms/input/Input.svelte +75 -0
  23. package/dist/atoms/input/Input.svelte.d.ts +4 -0
  24. package/dist/atoms/input/constants.d.ts +2 -0
  25. package/dist/atoms/input/constants.js +6 -0
  26. package/dist/atoms/input/types.d.ts +92 -0
  27. package/dist/atoms/text/Text.svelte +68 -0
  28. package/dist/atoms/text/Text.svelte.d.ts +4 -0
  29. package/dist/atoms/text/constants.d.ts +23 -0
  30. package/dist/atoms/text/constants.js +27 -0
  31. package/dist/atoms/text/types.d.ts +62 -0
  32. package/dist/index.d.ts +12 -0
  33. package/dist/index.js +11 -0
  34. package/dist/utils/cn.d.ts +6 -0
  35. package/dist/utils/cn.js +8 -0
  36. package/dist/utils/ecmc.css +126 -0
  37. package/package.json +91 -0
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # ecmc-design-core
2
+
3
+ Atoms and molecules for the ECMC design system built with Svelte 5.
4
+
5
+ ## Overview
6
+
7
+ This is an opinionated component library providing foundational UI components (atoms) and compound components (molecules) for building consistent user interfaces. The library is built with Svelte 5 and includes TypeScript support and Storybook integration.
8
+
9
+ ## Development
10
+
11
+ Start the development server:
12
+
13
+ ```sh
14
+ bun dev
15
+ # or
16
+ npm run dev
17
+ ```
18
+
19
+ View components in Storybook:
20
+
21
+ ```sh
22
+ bun storybook
23
+ # or
24
+ npm run storybook
25
+ ```
26
+
27
+ The Storybook interface will be available at `http://localhost:6006`.
28
+
29
+ ## Building
30
+
31
+ To build the preview app:
32
+
33
+ ```sh
34
+ bun build
35
+ # or
36
+ npm run build
37
+ ```
38
+
39
+ ## Scripts
40
+
41
+ - `dev` - Start development server
42
+ - `build` - Build the library for production
43
+ - `storybook` - Launch Storybook development server
44
+ - `build-storybook` - Build Storybook for deployment
45
+ - `lint` - Run linting checks
46
+ - `format` - Format code with Prettier
47
+ - `check` - Run Svelte type checking
48
+
49
+ ## License
50
+
51
+ MIT
52
+
53
+ ## Author
54
+
55
+ Arad Fadaei - [fadaei.dev](https://www.fadaei.dev)
@@ -0,0 +1,61 @@
1
+ <script lang="ts">
2
+ import Centered from '../container/sub/centered.container.svelte';
3
+ import Text from '../text/Text.svelte';
4
+ import { cn } from '../../utils/cn.js';
5
+ import { buttonVariantClasses, defaultProps } from './constants.js';
6
+ import type { ButtonProps } from './types.js';
7
+
8
+ let { children, onclick, variant = defaultProps.variant! }: ButtonProps = $props();
9
+
10
+ let computedClasses = $derived(cn(buttonVariantClasses[variant]));
11
+ </script>
12
+
13
+ <button class={computedClasses} disabled={variant === 'disabled'} {onclick}>
14
+ <Centered padding="xsm">
15
+ <Text>
16
+ {@render children?.()}
17
+ </Text>
18
+ </Centered>
19
+ </button>
20
+
21
+ <style>
22
+ button {
23
+ border: none;
24
+ border-radius: var(--rounding-size-1);
25
+ cursor: pointer;
26
+ }
27
+
28
+ .button--primary {
29
+ background-color: var(--primary-600);
30
+ color: var(--neutral-100);
31
+ }
32
+
33
+ .button--primary:hover {
34
+ background-color: var(--primary-700);
35
+ }
36
+
37
+ .button--primary:active {
38
+ background-color: var(--primary-900);
39
+ }
40
+
41
+ .button--secondary {
42
+ background-color: var(--neutral-400);
43
+ color: var(--neutral-100);
44
+ }
45
+
46
+ .button--secondary:hover {
47
+ background-color: var(--neutral-500);
48
+ color: var(--neutral-100);
49
+ }
50
+
51
+ .button--secondary:active {
52
+ background-color: var(--neutral-600);
53
+ }
54
+
55
+ .button--disabled {
56
+ background-color: var(--neutral-300);
57
+ color: var(--neutral-600);
58
+ cursor: not-allowed;
59
+ opacity: 0.6;
60
+ }
61
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { ButtonProps } from './types.js';
2
+ declare const Button: import("svelte").Component<ButtonProps, {}, "">;
3
+ type Button = ReturnType<typeof Button>;
4
+ export default Button;
@@ -0,0 +1,7 @@
1
+ import type { ButtonProps } from './types.js';
2
+ export declare const defaultProps: Partial<ButtonProps>;
3
+ export declare const buttonVariantClasses: {
4
+ readonly primary: "button--primary";
5
+ readonly secondary: "button--secondary";
6
+ readonly disabled: "button--disabled";
7
+ };
@@ -0,0 +1,8 @@
1
+ export const defaultProps = {
2
+ variant: 'primary'
3
+ };
4
+ export const buttonVariantClasses = {
5
+ primary: 'button--primary',
6
+ secondary: 'button--secondary',
7
+ disabled: 'button--disabled'
8
+ };
@@ -0,0 +1,35 @@
1
+ import type { Snippet } from 'svelte';
2
+
3
+ /**
4
+ * Props for the Button component
5
+ *
6
+ * @example
7
+ * ```svelte
8
+ * <Button variant="primary" onclick={handleClick}>
9
+ * Click Me
10
+ * </Button>
11
+ * ```
12
+ */
13
+ export interface ButtonProps {
14
+ /**
15
+ * The content to be rendered inside the button
16
+ */
17
+ children?: Snippet;
18
+
19
+ /**
20
+ * Visual variant that determines the button's appearance
21
+ * - `primary`: Main action button with prominent styling
22
+ * - `secondary`: Alternative action with less emphasis
23
+ * - `disabled`: Non-interactive state
24
+ *
25
+ * @default 'primary'
26
+ */
27
+ variant?: 'primary' | 'secondary' | 'disabled';
28
+
29
+ /**
30
+ * Click handler for button interactions
31
+ *
32
+ * @param event - The native mouse click event
33
+ */
34
+ onclick?: (event: MouseEvent) => void;
35
+ }
@@ -0,0 +1,106 @@
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+ import type { ContainerProps } from './types.js';
4
+ import { defaultProps, paddingClasses } from './constants.js';
5
+
6
+ // Props with defaults
7
+ let {
8
+ children,
9
+ padding = defaultProps.padding!,
10
+ fill = defaultProps.fill!,
11
+ metrics = $bindable(),
12
+ bg = defaultProps.bg!,
13
+ ...restProps
14
+ }: ContainerProps = $props();
15
+
16
+ let computedClasses = $derived(
17
+ cn(paddingClasses[padding], fill ? 'container--fill' : '', bg ? 'container--bg' : '')
18
+ );
19
+
20
+ // Container element reference
21
+ let containerElement: HTMLDivElement;
22
+
23
+ // Update metrics when element changes or on resize/scroll
24
+ function updateMetrics() {
25
+ if (!containerElement) return;
26
+
27
+ const rect = containerElement.getBoundingClientRect();
28
+
29
+ // Create a new metrics object to trigger reactivity
30
+ metrics = {
31
+ width: rect.width,
32
+ height: rect.height,
33
+ top: rect.top,
34
+ left: rect.left,
35
+ offsetTop: containerElement.offsetTop,
36
+ offsetLeft: containerElement.offsetLeft,
37
+ scrollWidth: containerElement.scrollWidth,
38
+ scrollHeight: containerElement.scrollHeight,
39
+ scrollTop: containerElement.scrollTop,
40
+ scrollLeft: containerElement.scrollLeft,
41
+ clientWidth: containerElement.clientWidth,
42
+ clientHeight: containerElement.clientHeight
43
+ };
44
+ }
45
+
46
+ // Initialize metrics when element is bound
47
+ $effect(() => {
48
+ if (containerElement) {
49
+ updateMetrics();
50
+
51
+ // Create ResizeObserver to track size changes
52
+ const resizeObserver = new ResizeObserver(() => {
53
+ updateMetrics();
54
+ });
55
+
56
+ resizeObserver.observe(containerElement);
57
+ containerElement.addEventListener('scroll', updateMetrics);
58
+
59
+ // Cleanup function
60
+ return () => {
61
+ resizeObserver.disconnect();
62
+ containerElement.removeEventListener('scroll', updateMetrics);
63
+ };
64
+ }
65
+ return () => {}; // Explicit return for when containerElement is not available
66
+ });
67
+ </script>
68
+
69
+ <div bind:this={containerElement} class={computedClasses} {...restProps}>
70
+ {@render children?.()}
71
+ </div>
72
+
73
+ <style>
74
+ .container--padding-none {
75
+ padding: var(--spacing-none);
76
+ }
77
+
78
+ .container--padding-xsm {
79
+ padding: var(--spacing-xsm);
80
+ }
81
+
82
+ .container--padding-sm {
83
+ padding: var(--spacing-sm);
84
+ }
85
+
86
+ .container--padding-md {
87
+ padding: var(--spacing-md);
88
+ }
89
+
90
+ .container--padding-lg {
91
+ padding: var(--spacing-lg);
92
+ }
93
+
94
+ .container--padding-xl {
95
+ padding: var(--spacing-xl);
96
+ }
97
+
98
+ .container--fill {
99
+ height: 100%;
100
+ width: 100%;
101
+ }
102
+
103
+ .container--bg {
104
+ background-color: light-dark(var(--neutral-200), var(--neutral-800));
105
+ }
106
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { ContainerProps } from './types.js';
2
+ declare const Container: import("svelte").Component<ContainerProps, {}, "metrics">;
3
+ type Container = ReturnType<typeof Container>;
4
+ export default Container;
@@ -0,0 +1,16 @@
1
+ import type { ContainerProps } from './types.js';
2
+ /**
3
+ * Default props for the container atom
4
+ */
5
+ export declare const defaultProps: Partial<ContainerProps>;
6
+ /**
7
+ * CSS class mappings for padding variants
8
+ */
9
+ export declare const paddingClasses: {
10
+ readonly none: "container--padding-none";
11
+ readonly xsm: "container--padding-xsm";
12
+ readonly sm: "container--padding-sm";
13
+ readonly md: "container--padding-md";
14
+ readonly lg: "container--padding-lg";
15
+ readonly xl: "container--padding-xl";
16
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Default props for the container atom
3
+ */
4
+ export const defaultProps = {
5
+ padding: 'md',
6
+ fill: false,
7
+ bg: false
8
+ };
9
+ /**
10
+ * CSS class mappings for padding variants
11
+ */
12
+ export const paddingClasses = {
13
+ none: 'container--padding-none',
14
+ xsm: 'container--padding-xsm',
15
+ sm: 'container--padding-sm',
16
+ md: 'container--padding-md',
17
+ lg: 'container--padding-lg',
18
+ xl: 'container--padding-xl'
19
+ };
@@ -0,0 +1,33 @@
1
+ <script lang="ts">
2
+ import Container from '../Container.svelte';
3
+ import type { InternalBoxProps } from '../types.js';
4
+
5
+ let {
6
+ children,
7
+ variant,
8
+ gap = 'md',
9
+ align = 'stretch',
10
+ justify = 'flex-start',
11
+ wrap = false,
12
+ metrics = $bindable(),
13
+ ...containerProps
14
+ }: InternalBoxProps = $props();
15
+
16
+ let flexWrap = $derived(wrap ? 'wrap' : 'nowrap');
17
+ let flexDirection = $derived(variant === 'vertical' ? 'column' : 'row');
18
+ </script>
19
+
20
+ <Container bind:metrics {...containerProps}>
21
+ <div
22
+ class="box"
23
+ style="gap: var(--spacing-{gap}); align-items: {align}; justify-content: {justify}; flex-wrap: {flexWrap}; flex-direction: {flexDirection};"
24
+ >
25
+ {@render children?.()}
26
+ </div>
27
+ </Container>
28
+
29
+ <style>
30
+ .box {
31
+ display: flex;
32
+ }
33
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { InternalBoxProps } from '../types.js';
2
+ declare const Box: import("svelte").Component<InternalBoxProps, {}, "metrics">;
3
+ type Box = ReturnType<typeof Box>;
4
+ export default Box;
@@ -0,0 +1,28 @@
1
+ <script lang="ts">
2
+ import Container from '../Container.svelte';
3
+ import type { CenteredProps } from '../types.js';
4
+
5
+ let {
6
+ children,
7
+ horizontal = true,
8
+ vertical = true,
9
+ metrics = $bindable(),
10
+ ...containerProps
11
+ }: CenteredProps = $props();
12
+
13
+ let justifyContent = $derived(horizontal ? 'center' : 'flex-start');
14
+ let alignItems = $derived(vertical ? 'center' : 'stretch');
15
+ </script>
16
+
17
+ <Container bind:metrics {...containerProps}>
18
+ <div class="centered" style="justify-content: {justifyContent}; align-items: {alignItems};">
19
+ {@render children?.()}
20
+ </div>
21
+ </Container>
22
+
23
+ <style>
24
+ .centered {
25
+ display: flex;
26
+ height: 100%;
27
+ }
28
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { CenteredProps } from '../types.js';
2
+ declare const Centered: import("svelte").Component<CenteredProps, {}, "metrics">;
3
+ type Centered = ReturnType<typeof Centered>;
4
+ export default Centered;
@@ -0,0 +1,32 @@
1
+ <script lang="ts">
2
+ import Container from '../Container.svelte';
3
+ import type { GridBoxProps } from '../types.js';
4
+
5
+ let {
6
+ children,
7
+ columns = 2,
8
+ gap = 'md',
9
+ autoFlow = 'row',
10
+ metrics = $bindable(),
11
+ ...containerProps
12
+ }: GridBoxProps = $props();
13
+
14
+ let gridTemplateColumns = $derived(
15
+ typeof columns === 'number' ? `repeat(${columns}, 1fr)` : columns
16
+ );
17
+ </script>
18
+
19
+ <Container bind:metrics {...containerProps}>
20
+ <div
21
+ class="gridbox"
22
+ style="grid-template-columns: {gridTemplateColumns}; gap: var(--spacing-{gap}); grid-auto-flow: {autoFlow};"
23
+ >
24
+ {@render children?.()}
25
+ </div>
26
+ </Container>
27
+
28
+ <style>
29
+ .gridbox {
30
+ display: grid;
31
+ }
32
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { GridBoxProps } from '../types.js';
2
+ declare const Gridbox: import("svelte").Component<GridBoxProps, {}, "metrics">;
3
+ type Gridbox = ReturnType<typeof Gridbox>;
4
+ export default Gridbox;
@@ -0,0 +1,10 @@
1
+ <script lang="ts">
2
+ import Box from './box.container.svelte';
3
+ import type { BoxProps } from '../types.js';
4
+
5
+ let { metrics = $bindable(), ...props }: BoxProps = $props();
6
+ </script>
7
+
8
+ <Box variant="horizontal" bind:metrics {...props}>
9
+ {@render props.children?.()}
10
+ </Box>
@@ -0,0 +1,4 @@
1
+ import type { BoxProps } from '../types.js';
2
+ declare const Hbox: import("svelte").Component<BoxProps, {}, "metrics">;
3
+ type Hbox = ReturnType<typeof Hbox>;
4
+ export default Hbox;
@@ -0,0 +1,10 @@
1
+ <script lang="ts">
2
+ import Box from './box.container.svelte';
3
+ import type { BoxProps } from '../types.js';
4
+
5
+ let { metrics = $bindable(), ...props }: BoxProps = $props();
6
+ </script>
7
+
8
+ <Box variant="vertical" bind:metrics {...props}>
9
+ {@render props.children?.()}
10
+ </Box>
@@ -0,0 +1,4 @@
1
+ import type { BoxProps } from '../types.js';
2
+ declare const Vbox: import("svelte").Component<BoxProps, {}, "metrics">;
3
+ type Vbox = ReturnType<typeof Vbox>;
4
+ export default Vbox;