fractalstyler2 0.4.1 → 0.7.0

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 (87) hide show
  1. package/README.md +114 -95
  2. package/dist/cli.js +105 -25
  3. package/dist/components/Accordion.svelte +44 -0
  4. package/dist/components/Accordion.svelte.d.ts +23 -0
  5. package/dist/components/AccordionItem.svelte +44 -0
  6. package/dist/components/AccordionItem.svelte.d.ts +21 -0
  7. package/dist/components/AppShell.svelte +86 -0
  8. package/dist/components/AppShell.svelte.d.ts +39 -0
  9. package/dist/components/ColorPicker.svelte +38 -0
  10. package/dist/components/ColorPicker.svelte.d.ts +6 -0
  11. package/dist/components/Hero.svelte +14 -0
  12. package/dist/components/Hero.svelte.d.ts +9 -0
  13. package/dist/components/LayoutPicker.svelte +34 -0
  14. package/dist/components/LayoutPicker.svelte.d.ts +6 -0
  15. package/dist/components/MotionPicker.svelte +34 -0
  16. package/dist/components/MotionPicker.svelte.d.ts +6 -0
  17. package/dist/components/PageShell.svelte +14 -0
  18. package/dist/components/PageShell.svelte.d.ts +9 -0
  19. package/dist/components/PageSplit.svelte +26 -0
  20. package/dist/components/PageSplit.svelte.d.ts +18 -0
  21. package/dist/components/ShapePicker.svelte +37 -0
  22. package/dist/components/ShapePicker.svelte.d.ts +6 -0
  23. package/dist/css/fractalstyler.css +10643 -0
  24. package/dist/css/fractalstyler.min.css +2 -0
  25. package/dist/index.d.ts +18 -6
  26. package/dist/index.js +30 -12
  27. package/dist/mcp/schemas/compile_fractals.json +3 -3
  28. package/dist/mcp/schemas/css_to_fractals.json +1 -1
  29. package/dist/mcp/schemas/generate_component.json +2 -2
  30. package/dist/mcp/schemas/instructions.md +41 -14
  31. package/dist/mcp/schemas/list_fractals.json +9 -7
  32. package/dist/mcp/schemas/validate_recipe.json +2 -2
  33. package/dist/mcp/server.d.ts +1 -1
  34. package/dist/mcp/server.js +320 -234
  35. package/dist/presets.core.d.ts +42 -0
  36. package/dist/presets.core.js +190 -0
  37. package/dist/presets.svelte.d.ts +6 -0
  38. package/dist/presets.svelte.js +21 -0
  39. package/dist/styles/_00_presets.sass +111 -0
  40. package/dist/styles/_00_themes.sass +1061 -0
  41. package/dist/styles/_00_tokens.sass +39 -17
  42. package/dist/styles/_01_config.sass +77 -70
  43. package/dist/styles/_02_dimensions.sass +174 -0
  44. package/dist/styles/_03_containers.sass +105 -0
  45. package/dist/styles/_04_layouts.sass +100 -0
  46. package/dist/styles/_05_shells.sass +374 -0
  47. package/dist/styles/_06_visuals.sass +236 -0
  48. package/dist/styles/_07_interactions.sass +112 -0
  49. package/dist/styles/_08_own.sass +4 -0
  50. package/dist/styles/canonical-markups.md +160 -0
  51. package/dist/styles/index.sass +11 -18
  52. package/dist/themes.d.ts +7 -0
  53. package/dist/themes.js +45 -0
  54. package/dist/version.d.ts +1 -0
  55. package/dist/version.js +2 -0
  56. package/package.json +26 -15
  57. package/plugin.json +11 -10
  58. package/registry.json +2002 -0
  59. package/skills/fractal-styler/SKILL.md +137 -50
  60. package/skills/fractal-styler/references/fractals.md +416 -28
  61. package/skills/fractal-styler/references/tokens.md +110 -36
  62. package/dist/styles/_02_fonts.sass +0 -13
  63. package/dist/styles/_03_responsive.sass +0 -31
  64. package/dist/styles/_04_atoms.sass +0 -155
  65. package/dist/styles/_05_molecules.sass +0 -97
  66. package/dist/styles/_06_recipes.sass +0 -189
  67. package/dist/styles/_07_base.sass +0 -44
  68. package/dist/styles/_08_blocks.sass +0 -433
  69. package/dist/styles/_09_utilities.sass +0 -208
  70. package/dist/styles/_10_layouts.sass +0 -374
  71. package/dist/styles/_11_own.sass +0 -21
  72. package/dist/styles/_fractals.sass +0 -14
  73. package/skills/style-migration/SKILL.md +0 -45
  74. package/templates/_00_tokens.sass +0 -154
  75. package/templates/_01_config.sass +0 -66
  76. package/templates/_02_fonts.sass +0 -13
  77. package/templates/_03_responsive.sass +0 -31
  78. package/templates/_04_atoms.sass +0 -155
  79. package/templates/_05_molecules.sass +0 -97
  80. package/templates/_06_recipes.sass +0 -189
  81. package/templates/_07_base.sass +0 -44
  82. package/templates/_08_blocks.sass +0 -433
  83. package/templates/_09_utilities.sass +0 -207
  84. package/templates/_10_layouts.sass +0 -374
  85. package/templates/_11_own.sass +0 -21
  86. package/templates/_fractals.sass +0 -14
  87. package/templates/index.sass +0 -18
@@ -0,0 +1,86 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ /**
5
+ * The canonical application shell, from canonical-markups.md §1 and §2.
6
+ *
7
+ * The point of this component is not convenience — the classes work by hand.
8
+ * It is that an L4 class without its markup is half a definition: the rails
9
+ * retract, the drawer opens and the TOC folds because of the *structure*,
10
+ * not because of anything you wire. Approximating the structure is where
11
+ * people quietly lose the behaviour and start inventing classes to get it
12
+ * back. This emits the structure exactly.
13
+ *
14
+ * Everything here is registry classes. There is no style block, and adding
15
+ * one would defeat the purpose.
16
+ */
17
+ interface Props {
18
+ /** Sticky top bar. Omit for a shell with no chrome. */
19
+ header?: Snippet;
20
+ /** Left rail — navigation. Visible ≥1024px, drawer below. */
21
+ sidebarLeft?: Snippet;
22
+ /** Right rail — table of contents. Visible ≥1280px, folds to `mobileToc`. */
23
+ sidebarRight?: Snippet;
24
+ /** The page-top disclosure the right rail retracts into below 1280px. */
25
+ mobileToc?: Snippet;
26
+ /** Bottom bar. */
27
+ footer?: Snippet;
28
+ /** Page content. Wrapped in `.content-shell` unless `bounded` is false. */
29
+ children: Snippet;
30
+ /**
31
+ * Whether the left rail is showing as a drawer. Only has an effect below
32
+ * 1024px, where the rail is off-canvas. Bind it to your menu button.
33
+ */
34
+ open?: boolean;
35
+ /** Set false to drop `.content-shell` and let content run full width. */
36
+ bounded?: boolean;
37
+ class?: string;
38
+ }
39
+
40
+ let {
41
+ header,
42
+ sidebarLeft,
43
+ sidebarRight,
44
+ mobileToc,
45
+ footer,
46
+ children,
47
+ open = $bindable(false),
48
+ bounded = true,
49
+ class: className = ''
50
+ }: Props = $props();
51
+ </script>
52
+
53
+ <div class="app-shell {className}" class:open>
54
+ {#if header}
55
+ <header class="app-header row ycenter xbetween gap-sm">
56
+ {@render header()}
57
+ </header>
58
+ {/if}
59
+
60
+ <main class="app-main">
61
+ {#if sidebarLeft}
62
+ <aside class="sidebar-left">{@render sidebarLeft()}</aside>
63
+ {/if}
64
+
65
+ <section class="main-section">
66
+ {#if mobileToc}
67
+ <details class="mobile-toc">{@render mobileToc()}</details>
68
+ {/if}
69
+ {#if bounded}
70
+ <article class="content-shell">{@render children()}</article>
71
+ {:else}
72
+ {@render children()}
73
+ {/if}
74
+ </section>
75
+
76
+ {#if sidebarRight}
77
+ <aside class="sidebar-right">{@render sidebarRight()}</aside>
78
+ {/if}
79
+ </main>
80
+
81
+ {#if footer}
82
+ <footer class="app-footer row ycenter xbetween text-xs text-muted">
83
+ {@render footer()}
84
+ </footer>
85
+ {/if}
86
+ </div>
@@ -0,0 +1,39 @@
1
+ import type { Snippet } from 'svelte';
2
+ /**
3
+ * The canonical application shell, from canonical-markups.md §1 and §2.
4
+ *
5
+ * The point of this component is not convenience — the classes work by hand.
6
+ * It is that an L4 class without its markup is half a definition: the rails
7
+ * retract, the drawer opens and the TOC folds because of the *structure*,
8
+ * not because of anything you wire. Approximating the structure is where
9
+ * people quietly lose the behaviour and start inventing classes to get it
10
+ * back. This emits the structure exactly.
11
+ *
12
+ * Everything here is registry classes. There is no style block, and adding
13
+ * one would defeat the purpose.
14
+ */
15
+ interface Props {
16
+ /** Sticky top bar. Omit for a shell with no chrome. */
17
+ header?: Snippet;
18
+ /** Left rail — navigation. Visible ≥1024px, drawer below. */
19
+ sidebarLeft?: Snippet;
20
+ /** Right rail — table of contents. Visible ≥1280px, folds to `mobileToc`. */
21
+ sidebarRight?: Snippet;
22
+ /** The page-top disclosure the right rail retracts into below 1280px. */
23
+ mobileToc?: Snippet;
24
+ /** Bottom bar. */
25
+ footer?: Snippet;
26
+ /** Page content. Wrapped in `.content-shell` unless `bounded` is false. */
27
+ children: Snippet;
28
+ /**
29
+ * Whether the left rail is showing as a drawer. Only has an effect below
30
+ * 1024px, where the rail is off-canvas. Bind it to your menu button.
31
+ */
32
+ open?: boolean;
33
+ /** Set false to drop `.content-shell` and let content run full width. */
34
+ bounded?: boolean;
35
+ class?: string;
36
+ }
37
+ declare const AppShell: import("svelte").Component<Props, {}, "open">;
38
+ type AppShell = ReturnType<typeof AppShell>;
39
+ export default AppShell;
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import { presetAxes, presets, initPresets, setPreset } from '../presets.svelte.js';
4
+
5
+ let { class: className = '' }: { class?: string } = $props();
6
+
7
+ onMount(() => initPresets());
8
+
9
+ // Layer-tint glyphs — one swatch, three intensities (least → most tinted).
10
+ const fills: Record<string, number> = { clean: 0, general: 0.45, vibrant: 1 };
11
+ </script>
12
+
13
+ <div class="row ycenter gap-8 {className}" role="group" aria-label="Color tint preset">
14
+ {#each presetAxes.color as color}
15
+ <button
16
+ type="button"
17
+ class="button ghost"
18
+ class:active={presets.color === color}
19
+ aria-pressed={presets.color === color}
20
+ title={color}
21
+ onclick={() => setPreset('color', color)}
22
+ >
23
+ <svg width="16" height="16" viewBox="0 0 19 19" aria-hidden="true">
24
+ <rect
25
+ x="1.5"
26
+ y="1.5"
27
+ width="16"
28
+ height="16"
29
+ rx="4"
30
+ fill="currentColor"
31
+ fill-opacity={fills[color]}
32
+ stroke="currentColor"
33
+ stroke-width="1.5"
34
+ />
35
+ </svg>
36
+ </button>
37
+ {/each}
38
+ </div>
@@ -0,0 +1,6 @@
1
+ type $$ComponentProps = {
2
+ class?: string;
3
+ };
4
+ declare const ColorPicker: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type ColorPicker = ReturnType<typeof ColorPicker>;
6
+ export default ColorPicker;
@@ -0,0 +1,14 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ /** The centred landing section, from canonical-markups.md §5. */
5
+ interface Props {
6
+ children: Snippet;
7
+ class?: string;
8
+ }
9
+ let { children, class: className = '' }: Props = $props();
10
+ </script>
11
+
12
+ <section class="hero {className}">
13
+ {@render children()}
14
+ </section>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ /** The centred landing section, from canonical-markups.md §5. */
3
+ interface Props {
4
+ children: Snippet;
5
+ class?: string;
6
+ }
7
+ declare const Hero: import("svelte").Component<Props, {}, "">;
8
+ type Hero = ReturnType<typeof Hero>;
9
+ export default Hero;
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import { presetAxes, presets, initPresets, setPreset } from '../presets.svelte.js';
4
+
5
+ let { class: className = '' }: { class?: string } = $props();
6
+
7
+ onMount(() => initPresets());
8
+
9
+ // Density glyphs — three bars, spread tightest → loosest.
10
+ const spreads: Record<string, number[]> = {
11
+ tight: [5.5, 8.5, 11.5],
12
+ comfortable: [3.5, 8.5, 13.5],
13
+ sprawling: [1.5, 8.5, 15.5]
14
+ };
15
+ </script>
16
+
17
+ <div class="row ycenter gap-8 {className}" role="group" aria-label="Layout density preset">
18
+ {#each presetAxes.layout as layout}
19
+ <button
20
+ type="button"
21
+ class="button ghost"
22
+ class:active={presets.layout === layout}
23
+ aria-pressed={presets.layout === layout}
24
+ title={layout}
25
+ onclick={() => setPreset('layout', layout)}
26
+ >
27
+ <svg width="16" height="16" viewBox="0 0 19 19" aria-hidden="true">
28
+ {#each spreads[layout] as y}
29
+ <rect x="3" {y} width="13" height="2" rx="1" fill="currentColor" />
30
+ {/each}
31
+ </svg>
32
+ </button>
33
+ {/each}
34
+ </div>
@@ -0,0 +1,6 @@
1
+ type $$ComponentProps = {
2
+ class?: string;
3
+ };
4
+ declare const LayoutPicker: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type LayoutPicker = ReturnType<typeof LayoutPicker>;
6
+ export default LayoutPicker;
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import { presetAxes, presets, initPresets, setPreset } from '../presets.svelte.js';
4
+
5
+ let { class: className = '' }: { class?: string } = $props();
6
+
7
+ onMount(() => initPresets());
8
+
9
+ // Energy glyphs — one arc, four amplitudes (still → liveliest overshoot).
10
+ const arcs: Record<string, number> = { reduced: 0, heavy: 4, active: 8, springy: 12 };
11
+ </script>
12
+
13
+ <div class="row ycenter gap-8 {className}" role="group" aria-label="Motion energy preset">
14
+ {#each presetAxes.motion as motion}
15
+ <button
16
+ type="button"
17
+ class="button ghost"
18
+ class:active={presets.motion === motion}
19
+ aria-pressed={presets.motion === motion}
20
+ title={motion}
21
+ onclick={() => setPreset('motion', motion)}
22
+ >
23
+ <svg width="16" height="16" viewBox="0 0 19 19" aria-hidden="true">
24
+ <path
25
+ d="M3 15 Q9.5 {15 - arcs[motion]} 16 15"
26
+ fill="none"
27
+ stroke="currentColor"
28
+ stroke-width="1.5"
29
+ stroke-linecap="round"
30
+ />
31
+ </svg>
32
+ </button>
33
+ {/each}
34
+ </div>
@@ -0,0 +1,6 @@
1
+ type $$ComponentProps = {
2
+ class?: string;
3
+ };
4
+ declare const MotionPicker: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type MotionPicker = ReturnType<typeof MotionPicker>;
6
+ export default MotionPicker;
@@ -0,0 +1,14 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ /** The padded content frame, from canonical-markups.md §4. Registry classes only. */
5
+ interface Props {
6
+ children: Snippet;
7
+ class?: string;
8
+ }
9
+ let { children, class: className = '' }: Props = $props();
10
+ </script>
11
+
12
+ <section class="page-shell {className}">
13
+ {@render children()}
14
+ </section>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ /** The padded content frame, from canonical-markups.md §4. Registry classes only. */
3
+ interface Props {
4
+ children: Snippet;
5
+ class?: string;
6
+ }
7
+ declare const PageShell: import("svelte").Component<Props, {}, "">;
8
+ type PageShell = ReturnType<typeof PageShell>;
9
+ export default PageShell;
@@ -0,0 +1,26 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ /**
5
+ * The full-bleed master-detail split, from canonical-markups.md §4.
6
+ *
7
+ * `.page-sidebar` and `.page-main` are not decoration: `.page-split` is a
8
+ * grid whose columns are defined for exactly those two children, and the
9
+ * horizontal padding lives in `.page-main` rather than on the split, so the
10
+ * sidebar can sit flush. Getting either wrong loses the layout silently.
11
+ */
12
+ interface Props {
13
+ /** Explorer / file tree. Hidden below 768px. */
14
+ sidebar?: Snippet;
15
+ children: Snippet;
16
+ class?: string;
17
+ }
18
+ let { sidebar, children, class: className = '' }: Props = $props();
19
+ </script>
20
+
21
+ <section class="page-split {className}">
22
+ {#if sidebar}
23
+ <aside class="page-sidebar">{@render sidebar()}</aside>
24
+ {/if}
25
+ <main class="page-main">{@render children()}</main>
26
+ </section>
@@ -0,0 +1,18 @@
1
+ import type { Snippet } from 'svelte';
2
+ /**
3
+ * The full-bleed master-detail split, from canonical-markups.md §4.
4
+ *
5
+ * `.page-sidebar` and `.page-main` are not decoration: `.page-split` is a
6
+ * grid whose columns are defined for exactly those two children, and the
7
+ * horizontal padding lives in `.page-main` rather than on the split, so the
8
+ * sidebar can sit flush. Getting either wrong loses the layout silently.
9
+ */
10
+ interface Props {
11
+ /** Explorer / file tree. Hidden below 768px. */
12
+ sidebar?: Snippet;
13
+ children: Snippet;
14
+ class?: string;
15
+ }
16
+ declare const PageSplit: import("svelte").Component<Props, {}, "">;
17
+ type PageSplit = ReturnType<typeof PageSplit>;
18
+ export default PageSplit;
@@ -0,0 +1,37 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import { presetAxes, presets, initPresets, setPreset } from '../presets.svelte.js';
4
+
5
+ let { class: className = '' }: { class?: string } = $props();
6
+
7
+ onMount(() => initPresets());
8
+
9
+ // Corner glyphs — one square, four geometries; rx mirrors the sm channel.
10
+ const glyphs: Record<string, number> = { sharp: 0, pro: 4, curved: 8, round: 16 };
11
+ </script>
12
+
13
+ <div class="row ycenter gap-8 {className}" role="group" aria-label="Corner shape preset">
14
+ {#each presetAxes.shape as shape}
15
+ <button
16
+ type="button"
17
+ class="button ghost"
18
+ class:active={presets.shape === shape}
19
+ aria-pressed={presets.shape === shape}
20
+ title={shape}
21
+ onclick={() => setPreset('shape', shape)}
22
+ >
23
+ <svg width="16" height="16" viewBox="0 0 19 19" aria-hidden="true">
24
+ <rect
25
+ x="1.5"
26
+ y="1.5"
27
+ width="16"
28
+ height="16"
29
+ rx={glyphs[shape]}
30
+ fill="none"
31
+ stroke="currentColor"
32
+ stroke-width="1.5"
33
+ />
34
+ </svg>
35
+ </button>
36
+ {/each}
37
+ </div>
@@ -0,0 +1,6 @@
1
+ type $$ComponentProps = {
2
+ class?: string;
3
+ };
4
+ declare const ShapePicker: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type ShapePicker = ReturnType<typeof ShapePicker>;
6
+ export default ShapePicker;