@eduardoalvarez/arrecife 0.5.0 → 0.6.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 (66) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +706 -470
  3. package/dist/brand/index.cjs +112 -95
  4. package/dist/brand/index.d.cts +40 -39
  5. package/dist/brand/index.d.ts +40 -39
  6. package/dist/brand/index.js +5 -4
  7. package/dist/catalog-D13txprv.d.cts +78 -0
  8. package/dist/catalog-D13txprv.d.ts +78 -0
  9. package/dist/chart/index.cjs +100 -83
  10. package/dist/chart/index.d.cts +66 -66
  11. package/dist/chart/index.d.ts +66 -66
  12. package/dist/chart/index.js +14 -12
  13. package/dist/chunk-25YNFCIF.js +141 -0
  14. package/dist/{chunk-YZ2SDOVZ.js → chunk-6O3KWB6P.js} +30 -30
  15. package/dist/chunk-CKRSQPTX.js +36 -0
  16. package/dist/{chunk-ZEOQKRQ7.js → chunk-DKCN7BAL.js} +1 -1
  17. package/dist/chunk-GCRII2KQ.js +86 -0
  18. package/dist/chunk-JMOOFZ3B.js +42 -0
  19. package/dist/chunk-O4TAH7YJ.js +276 -0
  20. package/dist/chunk-ODBFN44D.js +45 -0
  21. package/dist/{chunk-VPT32GPG.js → chunk-PMN7NR3G.js} +2 -2
  22. package/dist/chunk-XKYHTOUJ.js +27 -0
  23. package/dist/form/index.cjs +109 -92
  24. package/dist/form/index.d.cts +43 -42
  25. package/dist/form/index.d.ts +43 -42
  26. package/dist/form/index.js +25 -23
  27. package/dist/index.cjs +1068 -929
  28. package/dist/index.d.cts +770 -773
  29. package/dist/index.d.ts +770 -773
  30. package/dist/index.js +629 -675
  31. package/dist/{label-DuTvJGxD.d.ts → label-MgHFKnFy.d.cts} +3 -3
  32. package/dist/{label-DuTvJGxD.d.cts → label-MgHFKnFy.d.ts} +3 -3
  33. package/dist/og/index.cjs +130 -130
  34. package/dist/og/index.d.cts +93 -89
  35. package/dist/og/index.d.ts +93 -89
  36. package/dist/og/index.js +106 -106
  37. package/dist/shiki/index.cjs +28 -30
  38. package/dist/shiki/index.d.cts +4 -4
  39. package/dist/shiki/index.d.ts +4 -4
  40. package/dist/shiki/index.js +12 -12
  41. package/dist/theme/index.cjs +97 -0
  42. package/dist/theme/index.d.cts +144 -0
  43. package/dist/theme/index.d.ts +144 -0
  44. package/dist/theme/index.js +2 -0
  45. package/dist/tokens/index.cjs +133 -86
  46. package/dist/tokens/index.d.cts +246 -161
  47. package/dist/tokens/index.d.ts +246 -161
  48. package/dist/tokens/index.js +2 -2
  49. package/dist/tokens/theme.css +133 -98
  50. package/dist/variants/index.cjs +192 -0
  51. package/dist/variants/index.d.cts +192 -0
  52. package/dist/variants/index.d.ts +192 -0
  53. package/dist/variants/index.js +3 -0
  54. package/llms.txt +810 -744
  55. package/package.json +20 -11
  56. package/dist/catalogo-Du5ID-Hi.d.cts +0 -77
  57. package/dist/catalogo-Du5ID-Hi.d.ts +0 -77
  58. package/dist/chunk-E3OMP2DL.js +0 -36
  59. package/dist/chunk-KPZNNMV5.js +0 -83
  60. package/dist/chunk-NHS7ETKJ.js +0 -27
  61. package/dist/chunk-TSPJOM6K.js +0 -229
  62. package/dist/chunk-UOWIDFCB.js +0 -81
  63. package/dist/tema/index.cjs +0 -94
  64. package/dist/tema/index.d.cts +0 -110
  65. package/dist/tema/index.d.ts +0 -110
  66. package/dist/tema/index.js +0 -2
@@ -0,0 +1,97 @@
1
+ 'use strict';
2
+
3
+ // src/theme/index.ts
4
+ var THEME_KEY = "arrecife-theme";
5
+ var THEME_ATTRIBUTE = "data-theme";
6
+ var THEME_EVENT = "arrecife:theme";
7
+ var isTheme = (value) => value === "dark" || value === "light";
8
+ function currentTheme() {
9
+ if (typeof document === "undefined") return "dark";
10
+ const set = document.documentElement.getAttribute(THEME_ATTRIBUTE);
11
+ return isTheme(set) ? set : "dark";
12
+ }
13
+ function storedTheme() {
14
+ if (typeof localStorage === "undefined") return null;
15
+ try {
16
+ const value = localStorage.getItem(THEME_KEY);
17
+ return isTheme(value) ? value : null;
18
+ } catch {
19
+ return null;
20
+ }
21
+ }
22
+ function preferredTheme({ base } = {}) {
23
+ const stored = storedTheme();
24
+ if (stored) return stored;
25
+ if (base) return base;
26
+ if (typeof matchMedia === "undefined") return "dark";
27
+ return matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
28
+ }
29
+ function applyTheme(theme, persist = true) {
30
+ if (typeof document === "undefined") return;
31
+ document.documentElement.setAttribute(THEME_ATTRIBUTE, theme);
32
+ document.documentElement.style.colorScheme = theme;
33
+ if (persist) {
34
+ try {
35
+ localStorage.setItem(THEME_KEY, theme);
36
+ } catch {
37
+ }
38
+ }
39
+ dispatchEvent(new CustomEvent(THEME_EVENT, { detail: theme }));
40
+ }
41
+ function toggleTheme() {
42
+ const next = currentTheme() === "dark" ? "light" : "dark";
43
+ applyTheme(next);
44
+ return next;
45
+ }
46
+ function watchTheme(onChange, options = {}) {
47
+ if (typeof window === "undefined") return () => {
48
+ };
49
+ const own = (event) => {
50
+ const detail = event.detail;
51
+ if (isTheme(detail)) onChange(detail);
52
+ };
53
+ const otherTab = (event) => {
54
+ if (event.key !== THEME_KEY) return;
55
+ const theme = isTheme(event.newValue) ? event.newValue : preferredTheme(options);
56
+ applyTheme(theme, false);
57
+ onChange(theme);
58
+ };
59
+ addEventListener(THEME_EVENT, own);
60
+ addEventListener("storage", otherTab);
61
+ return () => {
62
+ removeEventListener(THEME_EVENT, own);
63
+ removeEventListener("storage", otherTab);
64
+ };
65
+ }
66
+ function themeScript({ base } = {}) {
67
+ return [
68
+ "(function () {",
69
+ " var KEY = " + JSON.stringify(THEME_KEY) + ";",
70
+ " function resolve() {",
71
+ " try {",
72
+ " var stored = localStorage.getItem(KEY);",
73
+ ' if (stored === "dark" || stored === "light") return stored;',
74
+ " } catch (e) {}",
75
+ base ? " return " + JSON.stringify(base) + ";" : ' return matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";',
76
+ " }",
77
+ " function apply() {",
78
+ " var theme = resolve();",
79
+ " document.documentElement.setAttribute(" + JSON.stringify(THEME_ATTRIBUTE) + ", theme);",
80
+ " document.documentElement.style.colorScheme = theme;",
81
+ " }",
82
+ " apply();",
83
+ ' document.addEventListener("astro:after-swap", apply);',
84
+ "})();"
85
+ ].join("\n");
86
+ }
87
+
88
+ exports.THEME_ATTRIBUTE = THEME_ATTRIBUTE;
89
+ exports.THEME_EVENT = THEME_EVENT;
90
+ exports.THEME_KEY = THEME_KEY;
91
+ exports.applyTheme = applyTheme;
92
+ exports.currentTheme = currentTheme;
93
+ exports.preferredTheme = preferredTheme;
94
+ exports.storedTheme = storedTheme;
95
+ exports.themeScript = themeScript;
96
+ exports.toggleTheme = toggleTheme;
97
+ exports.watchTheme = watchTheme;
@@ -0,0 +1,144 @@
1
+ /**
2
+ * The theme, without React.
3
+ *
4
+ * The library defines the WHOLE theming system — `@custom-variant light`, the
5
+ * `[data-theme]` blocks, the palette for both modes — and until now it exposed
6
+ * nothing that changes it. `eduardoalvarez.dev` and `links` each reimplemented
7
+ * that separately, with their own `localStorage` and their own
8
+ * `astro:after-swap`.
9
+ *
10
+ * This subpackage deliberately does not import React, exactly like `./tokens`,
11
+ * `./og` and `./shiki`: the two projects that need it most are Astro, and one of
12
+ * them ships no framework JavaScript at all. What gets published here is the
13
+ * hard part of the component — avoiding the first-paint flash and surviving
14
+ * navigation — not the button. The button is `ThemeToggle`; it lives at the root
15
+ * and uses this underneath.
16
+ *
17
+ * `check-package-exports.mjs` verifies that `./theme` does not drag React into
18
+ * the published `dist/`, same as the other three portable subpaths.
19
+ */
20
+ /** The two modes. Dark is primary and is the system default. */
21
+ type Theme = 'dark' | 'light';
22
+ /**
23
+ * The `localStorage` key.
24
+ *
25
+ * It carries the library name because `localStorage` belongs to the origin, not
26
+ * to the project: a bare `theme` collides with whatever else lives on the same
27
+ * domain.
28
+ */
29
+ declare const THEME_KEY = "arrecife-theme";
30
+ /** The attribute the `[data-theme]` blocks in `theme.css` read. */
31
+ declare const THEME_ATTRIBUTE = "data-theme";
32
+ /**
33
+ * The event emitted when the theme changes.
34
+ *
35
+ * It exists because `storage` only notifies the OTHER tabs: in the tab that made
36
+ * the change nothing fires, and a site with two theme controls — the header and
37
+ * the footer — would leave one of them showing the wrong icon.
38
+ */
39
+ declare const THEME_EVENT = "arrecife:theme";
40
+ /**
41
+ * The theme currently in place, read from the DOM.
42
+ *
43
+ * From the DOM and not from `localStorage`, deliberately: the head script has
44
+ * already resolved the stored preference against the system one, and resolving
45
+ * it again here is how the two answers drift apart.
46
+ */
47
+ declare function currentTheme(): Theme;
48
+ /**
49
+ * The stored preference, if any. `null` means «nobody has chosen», which is not
50
+ * the same as «chose dark»: with no choice, the system decides.
51
+ */
52
+ declare function storedTheme(): Theme | null;
53
+ /**
54
+ * What a site decides when nobody has chosen yet.
55
+ *
56
+ * `base` is not «the fallback», it is «this site IS this mode». Passing it stops
57
+ * the OS from being consulted at all, which is the whole point: the five
58
+ * projects are dark by decision, and with the OS in charge somebody running
59
+ * their machine in light mode saw the blog in light — the opposite of what was
60
+ * agreed.
61
+ *
62
+ * Left out, the OS decides and dark is the fallback. That was the only
63
+ * behaviour until 0.6.0, and it is still the right default for a library: a site
64
+ * that has not decided should follow the reader.
65
+ */
66
+ type ThemeOptions = {
67
+ /** The mode this site is. Given, `prefers-color-scheme` is not consulted. */
68
+ base?: Theme | undefined;
69
+ };
70
+ /**
71
+ * The theme that applies: whatever was chosen, and with no choice, `base` if the
72
+ * site declared one, else whatever the system asks for. With no
73
+ * `prefers-color-scheme` declared, dark, which is primary.
74
+ */
75
+ declare function preferredTheme({ base }?: ThemeOptions): Theme;
76
+ /**
77
+ * Sets the theme on `<html>` and persists it.
78
+ *
79
+ * It writes the attribute ALWAYS, including for `dark`. The system default does
80
+ * not need the attribute, but leaving it explicit is what lets a subtree declare
81
+ * the opposite mode — a code block sits on hull in both themes — without
82
+ * inheriting from an unmarked `<html>`.
83
+ */
84
+ declare function applyTheme(theme: Theme, persist?: boolean): void;
85
+ /** Switches to the opposite one and returns whichever stuck. */
86
+ declare function toggleTheme(): Theme;
87
+ /**
88
+ * Subscribes to theme changes and returns the function that cancels it.
89
+ *
90
+ * It listens to both sources: our own event — the control in this tab — and
91
+ * `storage`, which is a change made in another one. Without the second, two open
92
+ * tabs sit on different themes until one of them is reloaded.
93
+ */
94
+ declare function watchTheme(onChange: (theme: Theme) => void, options?: ThemeOptions): () => void;
95
+ /**
96
+ * The script that goes INLINE in the `<head>`, before any stylesheet.
97
+ *
98
+ * This is the hard part, and it is the part that got rewritten in every project.
99
+ * Without it the first paint comes out in the default theme and the correct one
100
+ * arrives a frame later: on a dark site that the reader left in light mode, that
101
+ * is a white flash on every load.
102
+ *
103
+ * It has to be a string and it has to be inline. A `<script src>`, even a
104
+ * synchronous one, gets downloaded: the flash comes back. So this is not a
105
+ * module you import, it is text you inject:
106
+ *
107
+ * ```astro
108
+ * ---
109
+ * import { themeScript } from '@eduardoalvarez/arrecife/theme';
110
+ * ---
111
+ * <head>
112
+ * <script is:inline set:html={themeScript} />
113
+ * </head>
114
+ * ```
115
+ *
116
+ * ```tsx
117
+ * // Next, in the root layout.
118
+ * <head>
119
+ * <script dangerouslySetInnerHTML={{ __html: themeScript }} />
120
+ * </head>
121
+ * ```
122
+ *
123
+ * It re-attaches on `astro:after-swap` because Astro's view transitions replace
124
+ * the whole `<html>`: without that line the theme is lost on navigation and the
125
+ * flash returns, this time mid-session.
126
+ *
127
+ * `base` is what the five projects were missing. All of them are dark BY
128
+ * DECISION — `eduardoalvarez.dev`'s own script said so out loud: «dark is the
129
+ * brand's PRIMARY mode, so it's the default and doesn't follow the OS setting».
130
+ * With the OS in charge, somebody running their machine in light mode saw the
131
+ * blog in light, which is the opposite of what was agreed, and there was no way
132
+ * to say otherwise: the export was a fixed string with no parameter. So those
133
+ * projects kept their own `public/theme.js` and the library published the hard
134
+ * part for nobody.
135
+ *
136
+ * Called with no options it behaves exactly as it did before: the OS decides and
137
+ * dark is the fallback. That is still the right default for a library — a site
138
+ * that has not decided should follow its reader.
139
+ *
140
+ * <script is:inline set:html={themeScript({ base: 'dark' })} />
141
+ */
142
+ declare function themeScript({ base }?: ThemeOptions): string;
143
+
144
+ export { THEME_ATTRIBUTE, THEME_EVENT, THEME_KEY, type Theme, type ThemeOptions, applyTheme, currentTheme, preferredTheme, storedTheme, themeScript, toggleTheme, watchTheme };
@@ -0,0 +1,144 @@
1
+ /**
2
+ * The theme, without React.
3
+ *
4
+ * The library defines the WHOLE theming system — `@custom-variant light`, the
5
+ * `[data-theme]` blocks, the palette for both modes — and until now it exposed
6
+ * nothing that changes it. `eduardoalvarez.dev` and `links` each reimplemented
7
+ * that separately, with their own `localStorage` and their own
8
+ * `astro:after-swap`.
9
+ *
10
+ * This subpackage deliberately does not import React, exactly like `./tokens`,
11
+ * `./og` and `./shiki`: the two projects that need it most are Astro, and one of
12
+ * them ships no framework JavaScript at all. What gets published here is the
13
+ * hard part of the component — avoiding the first-paint flash and surviving
14
+ * navigation — not the button. The button is `ThemeToggle`; it lives at the root
15
+ * and uses this underneath.
16
+ *
17
+ * `check-package-exports.mjs` verifies that `./theme` does not drag React into
18
+ * the published `dist/`, same as the other three portable subpaths.
19
+ */
20
+ /** The two modes. Dark is primary and is the system default. */
21
+ type Theme = 'dark' | 'light';
22
+ /**
23
+ * The `localStorage` key.
24
+ *
25
+ * It carries the library name because `localStorage` belongs to the origin, not
26
+ * to the project: a bare `theme` collides with whatever else lives on the same
27
+ * domain.
28
+ */
29
+ declare const THEME_KEY = "arrecife-theme";
30
+ /** The attribute the `[data-theme]` blocks in `theme.css` read. */
31
+ declare const THEME_ATTRIBUTE = "data-theme";
32
+ /**
33
+ * The event emitted when the theme changes.
34
+ *
35
+ * It exists because `storage` only notifies the OTHER tabs: in the tab that made
36
+ * the change nothing fires, and a site with two theme controls — the header and
37
+ * the footer — would leave one of them showing the wrong icon.
38
+ */
39
+ declare const THEME_EVENT = "arrecife:theme";
40
+ /**
41
+ * The theme currently in place, read from the DOM.
42
+ *
43
+ * From the DOM and not from `localStorage`, deliberately: the head script has
44
+ * already resolved the stored preference against the system one, and resolving
45
+ * it again here is how the two answers drift apart.
46
+ */
47
+ declare function currentTheme(): Theme;
48
+ /**
49
+ * The stored preference, if any. `null` means «nobody has chosen», which is not
50
+ * the same as «chose dark»: with no choice, the system decides.
51
+ */
52
+ declare function storedTheme(): Theme | null;
53
+ /**
54
+ * What a site decides when nobody has chosen yet.
55
+ *
56
+ * `base` is not «the fallback», it is «this site IS this mode». Passing it stops
57
+ * the OS from being consulted at all, which is the whole point: the five
58
+ * projects are dark by decision, and with the OS in charge somebody running
59
+ * their machine in light mode saw the blog in light — the opposite of what was
60
+ * agreed.
61
+ *
62
+ * Left out, the OS decides and dark is the fallback. That was the only
63
+ * behaviour until 0.6.0, and it is still the right default for a library: a site
64
+ * that has not decided should follow the reader.
65
+ */
66
+ type ThemeOptions = {
67
+ /** The mode this site is. Given, `prefers-color-scheme` is not consulted. */
68
+ base?: Theme | undefined;
69
+ };
70
+ /**
71
+ * The theme that applies: whatever was chosen, and with no choice, `base` if the
72
+ * site declared one, else whatever the system asks for. With no
73
+ * `prefers-color-scheme` declared, dark, which is primary.
74
+ */
75
+ declare function preferredTheme({ base }?: ThemeOptions): Theme;
76
+ /**
77
+ * Sets the theme on `<html>` and persists it.
78
+ *
79
+ * It writes the attribute ALWAYS, including for `dark`. The system default does
80
+ * not need the attribute, but leaving it explicit is what lets a subtree declare
81
+ * the opposite mode — a code block sits on hull in both themes — without
82
+ * inheriting from an unmarked `<html>`.
83
+ */
84
+ declare function applyTheme(theme: Theme, persist?: boolean): void;
85
+ /** Switches to the opposite one and returns whichever stuck. */
86
+ declare function toggleTheme(): Theme;
87
+ /**
88
+ * Subscribes to theme changes and returns the function that cancels it.
89
+ *
90
+ * It listens to both sources: our own event — the control in this tab — and
91
+ * `storage`, which is a change made in another one. Without the second, two open
92
+ * tabs sit on different themes until one of them is reloaded.
93
+ */
94
+ declare function watchTheme(onChange: (theme: Theme) => void, options?: ThemeOptions): () => void;
95
+ /**
96
+ * The script that goes INLINE in the `<head>`, before any stylesheet.
97
+ *
98
+ * This is the hard part, and it is the part that got rewritten in every project.
99
+ * Without it the first paint comes out in the default theme and the correct one
100
+ * arrives a frame later: on a dark site that the reader left in light mode, that
101
+ * is a white flash on every load.
102
+ *
103
+ * It has to be a string and it has to be inline. A `<script src>`, even a
104
+ * synchronous one, gets downloaded: the flash comes back. So this is not a
105
+ * module you import, it is text you inject:
106
+ *
107
+ * ```astro
108
+ * ---
109
+ * import { themeScript } from '@eduardoalvarez/arrecife/theme';
110
+ * ---
111
+ * <head>
112
+ * <script is:inline set:html={themeScript} />
113
+ * </head>
114
+ * ```
115
+ *
116
+ * ```tsx
117
+ * // Next, in the root layout.
118
+ * <head>
119
+ * <script dangerouslySetInnerHTML={{ __html: themeScript }} />
120
+ * </head>
121
+ * ```
122
+ *
123
+ * It re-attaches on `astro:after-swap` because Astro's view transitions replace
124
+ * the whole `<html>`: without that line the theme is lost on navigation and the
125
+ * flash returns, this time mid-session.
126
+ *
127
+ * `base` is what the five projects were missing. All of them are dark BY
128
+ * DECISION — `eduardoalvarez.dev`'s own script said so out loud: «dark is the
129
+ * brand's PRIMARY mode, so it's the default and doesn't follow the OS setting».
130
+ * With the OS in charge, somebody running their machine in light mode saw the
131
+ * blog in light, which is the opposite of what was agreed, and there was no way
132
+ * to say otherwise: the export was a fixed string with no parameter. So those
133
+ * projects kept their own `public/theme.js` and the library published the hard
134
+ * part for nobody.
135
+ *
136
+ * Called with no options it behaves exactly as it did before: the OS decides and
137
+ * dark is the fallback. That is still the right default for a library — a site
138
+ * that has not decided should follow its reader.
139
+ *
140
+ * <script is:inline set:html={themeScript({ base: 'dark' })} />
141
+ */
142
+ declare function themeScript({ base }?: ThemeOptions): string;
143
+
144
+ export { THEME_ATTRIBUTE, THEME_EVENT, THEME_KEY, type Theme, type ThemeOptions, applyTheme, currentTheme, preferredTheme, storedTheme, themeScript, toggleTheme, watchTheme };
@@ -0,0 +1,2 @@
1
+ export { THEME_ATTRIBUTE, THEME_EVENT, THEME_KEY, applyTheme, currentTheme, preferredTheme, storedTheme, themeScript, toggleTheme, watchTheme } from '../chunk-GCRII2KQ.js';
2
+ import '../chunk-MLKGABMK.js';