@resq-systems/constants 0.4.0 → 0.5.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.
package/lib/brand.d.ts CHANGED
@@ -15,8 +15,15 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  /**
18
- * ResQ Systems brand identity — names, domains, contact addresses, and legal details
19
- * shared across apps (marketing site, dashboard, transactional email).
18
+ * @fileoverview ResQ Systems brand identity constants — names, domains, contact
19
+ * addresses, and legal details shared across apps (marketing site, dashboard,
20
+ * transactional email).
21
+ *
22
+ * @module @resq-systems/constants/brand
23
+ */
24
+ /**
25
+ * ResQ Systems brand identity — names, domains, contact addresses, and legal
26
+ * details shared across apps (marketing site, dashboard, transactional email).
20
27
  *
21
28
  * The postal address is ResQ Systems, Inc.'s public Delaware registered-agent
22
29
  * address (already public on the DE filing), included so commercial email stays
@@ -33,6 +40,11 @@ declare const brand: {
33
40
  readonly tagline: "autonomous drone disaster response";
34
41
  /** Long-form product description (metadata, manifest, store listings). */
35
42
  readonly description: "The decentralized kinetic operating system for autonomous disaster response. Mesh-networked coordination when infrastructure fails.";
43
+ /**
44
+ * Absolute `https://` origins with no trailing slash, so a caller can append
45
+ * a path directly (`` `${brand.domains.marketing}/pricing` ``). `marketing`
46
+ * is the apex domain; the others are subdomains of it.
47
+ */
36
48
  readonly domains: {
37
49
  readonly app: "https://app.resq.software";
38
50
  readonly marketing: "https://resq.software";
@@ -40,9 +52,26 @@ declare const brand: {
40
52
  readonly status: "https://status.resq.software";
41
53
  };
42
54
  readonly email: {
55
+ /**
56
+ * RFC 5322 display-name form (`Name <addr>`) for use as a message `From`
57
+ * header verbatim. Sends from the `send.resq.software` subdomain — the
58
+ * DKIM/SPF-authenticated envelope domain — which differs from the apex
59
+ * reply mailboxes such as {@link brand.email.contact} and {@link brand.email.security}.
60
+ */
43
61
  readonly from: "ResQ Systems <updates@send.resq.software>";
44
- readonly support: "support@resq.software";
62
+ /**
63
+ * General support address. Currently an alias of {@link brand.email.contact} — there
64
+ * is no dedicated `support@` mailbox — so replies land in the same inbox.
65
+ */
66
+ readonly support: "contact@resq.software";
67
+ /** General contact / inbound inquiries. */
45
68
  readonly contact: "contact@resq.software";
69
+ /** Security & vulnerability reports; the address to publish in `security.txt`. */
70
+ readonly security: "security@resq.software";
71
+ /** Research, press, and partnership inquiries. */
72
+ readonly research: "research@resq.software";
73
+ /** Engineering / automation address — matches the CI commit author. */
74
+ readonly engineer: "engineer@resq.software";
46
75
  };
47
76
  readonly legal: {
48
77
  readonly termsUrl: "https://resq.software/legal/terms";
@@ -56,8 +85,8 @@ declare const brand: {
56
85
  readonly github: "https://github.com/resq-software";
57
86
  };
58
87
  readonly company: {
59
- readonly stage: "Seed Stage";
60
- readonly locations: readonly ["New York", "Texas"];
88
+ readonly stage: "Pre-Seed";
89
+ readonly locations: readonly ["Long Island, New York"];
61
90
  };
62
91
  readonly logo: "https://resq.software/logo.png";
63
92
  readonly postalAddress: "ResQ Systems, Inc., 131 Continental Dr, Suite 305, Newark, DE 19713, USA";
@@ -1 +1 @@
1
- {"version":3,"file":"brand.d.ts","names":[],"sources":["../src/brand.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;cAwBa;;WAEZ;;WAEA;;WAEA;;WAEA;;WAEA;WAEA;aACC;aACA;aACA;aACA;;WAED;aACC;aACA;aACA;;WAED;aACC;aACA;;WAED;aACC;;aAEA;aACA;aACA;;WAED;aACC;aACA;;WAED;WACA"}
1
+ {"version":3,"file":"brand.d.ts","names":[],"sources":["../src/brand.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgCa;;WAEZ;;WAEA;;WAEA;;WAEA;;WAEA;;;;;;WAOA;aACC;aACA;aACA;aACA;;WAED;;;;;;;aAOC;;;;;aAKA;;aAEA;;aAEA;;aAEA;;aAEA;;WAED;aACC;aACA;;WAED;aACC;;aAEA;aACA;aACA;;WAED;aACC;aACA;;WAED;WACA"}
package/lib/brand.js CHANGED
@@ -15,8 +15,15 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  /**
18
- * ResQ Systems brand identity — names, domains, contact addresses, and legal details
19
- * shared across apps (marketing site, dashboard, transactional email).
18
+ * @fileoverview ResQ Systems brand identity constants — names, domains, contact
19
+ * addresses, and legal details shared across apps (marketing site, dashboard,
20
+ * transactional email).
21
+ *
22
+ * @module @resq-systems/constants/brand
23
+ */
24
+ /**
25
+ * ResQ Systems brand identity — names, domains, contact addresses, and legal
26
+ * details shared across apps (marketing site, dashboard, transactional email).
20
27
  *
21
28
  * The postal address is ResQ Systems, Inc.'s public Delaware registered-agent
22
29
  * address (already public on the DE filing), included so commercial email stays
@@ -33,6 +40,11 @@ const brand = {
33
40
  tagline: "autonomous drone disaster response",
34
41
  /** Long-form product description (metadata, manifest, store listings). */
35
42
  description: "The decentralized kinetic operating system for autonomous disaster response. Mesh-networked coordination when infrastructure fails.",
43
+ /**
44
+ * Absolute `https://` origins with no trailing slash, so a caller can append
45
+ * a path directly (`` `${brand.domains.marketing}/pricing` ``). `marketing`
46
+ * is the apex domain; the others are subdomains of it.
47
+ */
36
48
  domains: {
37
49
  app: "https://app.resq.software",
38
50
  marketing: "https://resq.software",
@@ -40,9 +52,26 @@ const brand = {
40
52
  status: "https://status.resq.software"
41
53
  },
42
54
  email: {
55
+ /**
56
+ * RFC 5322 display-name form (`Name <addr>`) for use as a message `From`
57
+ * header verbatim. Sends from the `send.resq.software` subdomain — the
58
+ * DKIM/SPF-authenticated envelope domain — which differs from the apex
59
+ * reply mailboxes such as {@link brand.email.contact} and {@link brand.email.security}.
60
+ */
43
61
  from: "ResQ Systems <updates@send.resq.software>",
44
- support: "support@resq.software",
45
- contact: "contact@resq.software"
62
+ /**
63
+ * General support address. Currently an alias of {@link brand.email.contact} — there
64
+ * is no dedicated `support@` mailbox — so replies land in the same inbox.
65
+ */
66
+ support: "contact@resq.software",
67
+ /** General contact / inbound inquiries. */
68
+ contact: "contact@resq.software",
69
+ /** Security & vulnerability reports; the address to publish in `security.txt`. */
70
+ security: "security@resq.software",
71
+ /** Research, press, and partnership inquiries. */
72
+ research: "research@resq.software",
73
+ /** Engineering / automation address — matches the CI commit author. */
74
+ engineer: "engineer@resq.software"
46
75
  },
47
76
  legal: {
48
77
  termsUrl: "https://resq.software/legal/terms",
@@ -56,8 +85,8 @@ const brand = {
56
85
  github: "https://github.com/resq-software"
57
86
  },
58
87
  company: {
59
- stage: "Seed Stage",
60
- locations: ["New York", "Texas"]
88
+ stage: "Pre-Seed",
89
+ locations: ["Long Island, New York"]
61
90
  },
62
91
  logo: "https://resq.software/logo.png",
63
92
  postalAddress: "ResQ Systems, Inc., 131 Continental Dr, Suite 305, Newark, DE 19713, USA"
package/lib/brand.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"brand.js","names":[],"sources":["../src/brand.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * ResQ Systems brand identity — names, domains, contact addresses, and legal details\n * shared across apps (marketing site, dashboard, transactional email).\n *\n * The postal address is ResQ Systems, Inc.'s public Delaware registered-agent\n * address (already public on the DE filing), included so commercial email stays\n * CAN-SPAM compliant by default.\n */\nexport const brand = {\n\t/** Short brand name. */\n\tname: \"ResQ Systems\",\n\t/** Product name (marketing / app title). */\n\tproductName: \"ResQ Tactical OS\",\n\t/** Registered legal entity. */\n\tlegalName: \"ResQ Systems, Inc.\",\n\t/** One-line positioning tagline. */\n\ttagline: \"autonomous drone disaster response\",\n\t/** Long-form product description (metadata, manifest, store listings). */\n\tdescription:\n\t\t\"The decentralized kinetic operating system for autonomous disaster response. Mesh-networked coordination when infrastructure fails.\",\n\tdomains: {\n\t\tapp: \"https://app.resq.software\",\n\t\tmarketing: \"https://resq.software\",\n\t\tdocs: \"https://docs.resq.software\",\n\t\tstatus: \"https://status.resq.software\",\n\t},\n\temail: {\n\t\tfrom: \"ResQ Systems <updates@send.resq.software>\",\n\t\tsupport: \"support@resq.software\",\n\t\tcontact: \"contact@resq.software\",\n\t},\n\tlegal: {\n\t\ttermsUrl: \"https://resq.software/legal/terms\",\n\t\tprivacyUrl: \"https://resq.software/legal/privacy\",\n\t},\n\tsocials: {\n\t\tx: \"https://x.com/resqsystems_inc\",\n\t\t/** The `@handle` form for `twitter:creator`/`site` meta (matches the `x` profile). */\n\t\txHandle: \"@resqsystems_inc\",\n\t\tlinkedin: \"https://www.linkedin.com/company/resq-systems-inc\",\n\t\tgithub: \"https://github.com/resq-software\",\n\t},\n\tcompany: {\n\t\tstage: \"Seed Stage\",\n\t\tlocations: [\"New York\", \"Texas\"],\n\t},\n\tlogo: \"https://resq.software/logo.png\",\n\tpostalAddress: \"ResQ Systems, Inc., 131 Continental Dr, Suite 305, Newark, DE 19713, USA\",\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,QAAQ;;CAEpB,MAAM;;CAEN,aAAa;;CAEb,WAAW;;CAEX,SAAS;;CAET,aACC;CACD,SAAS;EACR,KAAK;EACL,WAAW;EACX,MAAM;EACN,QAAQ;CACT;CACA,OAAO;EACN,MAAM;EACN,SAAS;EACT,SAAS;CACV;CACA,OAAO;EACN,UAAU;EACV,YAAY;CACb;CACA,SAAS;EACR,GAAG;;EAEH,SAAS;EACT,UAAU;EACV,QAAQ;CACT;CACA,SAAS;EACR,OAAO;EACP,WAAW,CAAC,YAAY,OAAO;CAChC;CACA,MAAM;CACN,eAAe;AAChB"}
1
+ {"version":3,"file":"brand.js","names":[],"sources":["../src/brand.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview ResQ Systems brand identity constants — names, domains, contact\n * addresses, and legal details shared across apps (marketing site, dashboard,\n * transactional email).\n *\n * @module @resq-systems/constants/brand\n */\n\n/**\n * ResQ Systems brand identity — names, domains, contact addresses, and legal\n * details shared across apps (marketing site, dashboard, transactional email).\n *\n * The postal address is ResQ Systems, Inc.'s public Delaware registered-agent\n * address (already public on the DE filing), included so commercial email stays\n * CAN-SPAM compliant by default.\n */\nexport const brand = {\n\t/** Short brand name. */\n\tname: \"ResQ Systems\",\n\t/** Product name (marketing / app title). */\n\tproductName: \"ResQ Tactical OS\",\n\t/** Registered legal entity. */\n\tlegalName: \"ResQ Systems, Inc.\",\n\t/** One-line positioning tagline. */\n\ttagline: \"autonomous drone disaster response\",\n\t/** Long-form product description (metadata, manifest, store listings). */\n\tdescription:\n\t\t\"The decentralized kinetic operating system for autonomous disaster response. Mesh-networked coordination when infrastructure fails.\",\n\t/**\n\t * Absolute `https://` origins with no trailing slash, so a caller can append\n\t * a path directly (`` `${brand.domains.marketing}/pricing` ``). `marketing`\n\t * is the apex domain; the others are subdomains of it.\n\t */\n\tdomains: {\n\t\tapp: \"https://app.resq.software\",\n\t\tmarketing: \"https://resq.software\",\n\t\tdocs: \"https://docs.resq.software\",\n\t\tstatus: \"https://status.resq.software\",\n\t},\n\temail: {\n\t\t/**\n\t\t * RFC 5322 display-name form (`Name <addr>`) for use as a message `From`\n\t\t * header verbatim. Sends from the `send.resq.software` subdomain — the\n\t\t * DKIM/SPF-authenticated envelope domain — which differs from the apex\n\t\t * reply mailboxes such as {@link brand.email.contact} and {@link brand.email.security}.\n\t\t */\n\t\tfrom: \"ResQ Systems <updates@send.resq.software>\",\n\t\t/**\n\t\t * General support address. Currently an alias of {@link brand.email.contact} — there\n\t\t * is no dedicated `support@` mailbox — so replies land in the same inbox.\n\t\t */\n\t\tsupport: \"contact@resq.software\",\n\t\t/** General contact / inbound inquiries. */\n\t\tcontact: \"contact@resq.software\",\n\t\t/** Security & vulnerability reports; the address to publish in `security.txt`. */\n\t\tsecurity: \"security@resq.software\",\n\t\t/** Research, press, and partnership inquiries. */\n\t\tresearch: \"research@resq.software\",\n\t\t/** Engineering / automation address — matches the CI commit author. */\n\t\tengineer: \"engineer@resq.software\",\n\t},\n\tlegal: {\n\t\ttermsUrl: \"https://resq.software/legal/terms\",\n\t\tprivacyUrl: \"https://resq.software/legal/privacy\",\n\t},\n\tsocials: {\n\t\tx: \"https://x.com/resqsystems_inc\",\n\t\t/** The `@handle` form for `twitter:creator`/`site` meta (matches the `x` profile). */\n\t\txHandle: \"@resqsystems_inc\",\n\t\tlinkedin: \"https://www.linkedin.com/company/resq-systems-inc\",\n\t\tgithub: \"https://github.com/resq-software\",\n\t},\n\tcompany: {\n\t\tstage: \"Pre-Seed\",\n\t\tlocations: [\"Long Island, New York\"],\n\t},\n\tlogo: \"https://resq.software/logo.png\",\n\tpostalAddress: \"ResQ Systems, Inc., 131 Continental Dr, Suite 305, Newark, DE 19713, USA\",\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAa,QAAQ;;CAEpB,MAAM;;CAEN,aAAa;;CAEb,WAAW;;CAEX,SAAS;;CAET,aACC;;;;;;CAMD,SAAS;EACR,KAAK;EACL,WAAW;EACX,MAAM;EACN,QAAQ;CACT;CACA,OAAO;;;;;;;EAON,MAAM;;;;;EAKN,SAAS;;EAET,SAAS;;EAET,UAAU;;EAEV,UAAU;;EAEV,UAAU;CACX;CACA,OAAO;EACN,UAAU;EACV,YAAY;CACb;CACA,SAAS;EACR,GAAG;;EAEH,SAAS;EACT,UAAU;EACV,QAAQ;CACT;CACA,SAAS;EACR,OAAO;EACP,WAAW,CAAC,uBAAuB;CACpC;CACA,MAAM;CACN,eAAe;AAChB"}
package/lib/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { brand } from "./brand.js";
2
2
  import { ColorRole, ColorTokenName, OklchColorRole, StatusRole, colors, fonts, radii, themeColor } from "./tokens.js";
3
- export { ColorRole, ColorTokenName, OklchColorRole, StatusRole, brand, colors, fonts, radii, themeColor };
3
+ export { type ColorRole, type ColorTokenName, type OklchColorRole, type StatusRole, brand, colors, fonts, radii, themeColor };
package/lib/tokens.d.ts CHANGED
@@ -15,25 +15,51 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  /**
18
- * ResQ Systems design tokens the single source of truth shared by `@resq-systems/ui`,
19
- * `@resq-systems/email-templates`, and app surfaces.
18
+ * @fileoverview ResQ Systems design tokens (colors, theme colors, fonts, radii)
19
+ * the single source of truth shared by `@resq-systems/ui`,
20
+ * `@resq-systems/email-templates`, and app surfaces. `oklch` is the design-system
21
+ * source of truth; `hex` is the email/legacy-safe snapshot (email clients and
22
+ * older targets do not support `oklch()`), so keep the two representations in sync
23
+ * when the palette changes.
20
24
  *
21
- * `oklch` is the design-system source of truth; `hex` is the email/legacy-safe
22
- * snapshot (email clients and older targets do not support `oklch()`). Keep the
23
- * two representations in sync when the palette changes.
25
+ * @module @resq-systems/constants/tokens
24
26
  */
25
27
  /**
26
28
  * The six canonical color roles present in **both** representations. `oklch`
27
29
  * (the design-system source of truth) and `hex` (the email-safe snapshot) must
28
30
  * each define every one of these.
31
+ *
32
+ * These are semantic *roles*, not raw swatches: consumers reference
33
+ * `colors.oklch.primary`, never the literal channel values, so a palette change
34
+ * updates the token once. The union has no meaningful ordering — membership, not
35
+ * position, is the contract.
29
36
  */
30
37
  type ColorRole = "background" | "surface" | "border" | "foreground" | "muted" | "primary";
31
38
  /**
32
39
  * Status roles that exist only in the email-safe `hex` snapshot. `oklch` does
33
40
  * not define these, so they are indexable on `colors.hex` but never on
34
- * `colors.oklch`.
41
+ * {@link ColorRole} / `colors.oklch` — the type split enforces that asymmetry at
42
+ * compile time. In apps these four states come from the `@resq-systems/ui`
43
+ * theme's own status tokens rather than from here; the hex copies exist so
44
+ * transactional email (which can't evaluate `oklch()`) still has them.
35
45
  */
36
46
  type StatusRole = "info" | "success" | "warning" | "danger";
47
+ /**
48
+ * The canonical palette in its two representations. `oklch` is the source of
49
+ * truth; `hex` is a hand-maintained snapshot that must resolve to the same
50
+ * perceived color for each shared {@link ColorRole}, because email clients and
51
+ * older render targets can't evaluate `oklch()`. Editing one representation
52
+ * without the other silently drifts email away from the app — the two are only
53
+ * *structurally* linked by the `satisfies` clause below, not value-checked.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { colors } from "@resq-systems/constants/tokens";
58
+ *
59
+ * colors.oklch.primary; // → "oklch(58.50% 0.1877 24.72)"
60
+ * colors.hex.danger; // → "#D43E3F" (status role — hex only)
61
+ * ```
62
+ */
37
63
  declare const colors: {
38
64
  readonly oklch: {
39
65
  readonly background: "oklch(16.63% 0.0262 269.37)";
@@ -71,14 +97,27 @@ type OklchColorRole = keyof typeof colors.oklch;
71
97
  /** Every token name present on the email-safe `hex` snapshot. */
72
98
  type ColorTokenName = keyof typeof colors.hex;
73
99
  /**
74
- * Browser + PWA `theme-color` / viewport meta colors. `dark` tracks the
75
- * canonical page background; `light` is the light-mode chrome color.
100
+ * Browser + PWA `theme-color` / viewport meta colors, keyed by
101
+ * `prefers-color-scheme`. `dark` is aliased to {@link colors}`.hex.background`
102
+ * (not a re-typed copy) so the browser chrome always matches the dark page
103
+ * background exactly; `light` is a standalone light-mode chrome color with no
104
+ * palette counterpart. Hex, not oklch, because `<meta name="theme-color">`
105
+ * across browsers doesn't accept `oklch()`.
76
106
  */
77
107
  declare const themeColor: {
78
108
  readonly light: "#E8EAF0";
79
109
  readonly dark: "#0A0E1A";
80
110
  };
81
- /** Brand typefaces, ready-to-use CSS font stacks, and the webfont stylesheet. */
111
+ /**
112
+ * Brand typefaces, ready-to-use CSS font stacks, and the webfont stylesheet.
113
+ *
114
+ * Within each {@link fonts.stacks} array the **first** entry is the brand face
115
+ * and the rest are ordered fallbacks the browser walks until one resolves;
116
+ * multi-word family names are pre-quoted so the array can be joined into a
117
+ * `font-family` value verbatim. {@link fonts.googleFontsHref} must stay in sync
118
+ * with these families and the weights they're actually rendered at — a face or
119
+ * weight used in the app but missing from the href won't load.
120
+ */
82
121
  declare const fonts: {
83
122
  readonly display: "Syne";
84
123
  readonly body: "DM Sans";
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","names":[],"sources":["../src/tokens.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6BY;;;;;;KAOA;cAEC;;aAEX;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;;;;;;;;;;;;;;KAyBU,8BAA8B,OAAO;;KAGrC,8BAA8B,OAAO;;;;;cAMpC;WACZ;WACA;;;cAIY;WACZ;WACA;WACA;WACA;aACC;aACA;aAUA;;WAED;;;;;;;cASY;WACZ;WACA;WACA;WACA;WACA"}
1
+ {"version":3,"file":"tokens.d.ts","names":[],"sources":["../src/tokens.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqCY;;;;;;;;;KAUA;;;;;;;;;;;;;;;;;cAkBC;;aAEX;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;;;;;;;;;;;;;;KAyBU,8BAA8B,OAAO;;KAGrC,8BAA8B,OAAO;;;;;;;;;cAUpC;WACZ;WACA;;;;;;;;;;;;cAaY;WACZ;WACA;WACA;WACA;aACC;aACA;aAUA;;WAED;;;;;;;cASY;WACZ;WACA;WACA;WACA;WACA"}
package/lib/tokens.js CHANGED
@@ -1,4 +1,20 @@
1
1
  //#region src/tokens.ts
2
+ /**
3
+ * The canonical palette in its two representations. `oklch` is the source of
4
+ * truth; `hex` is a hand-maintained snapshot that must resolve to the same
5
+ * perceived color for each shared {@link ColorRole}, because email clients and
6
+ * older render targets can't evaluate `oklch()`. Editing one representation
7
+ * without the other silently drifts email away from the app — the two are only
8
+ * *structurally* linked by the `satisfies` clause below, not value-checked.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { colors } from "@resq-systems/constants/tokens";
13
+ *
14
+ * colors.oklch.primary; // → "oklch(58.50% 0.1877 24.72)"
15
+ * colors.hex.danger; // → "#D43E3F" (status role — hex only)
16
+ * ```
17
+ */
2
18
  const colors = {
3
19
  oklch: {
4
20
  background: "oklch(16.63% 0.0262 269.37)",
@@ -34,14 +50,27 @@ const colors = {
34
50
  ]
35
51
  };
36
52
  /**
37
- * Browser + PWA `theme-color` / viewport meta colors. `dark` tracks the
38
- * canonical page background; `light` is the light-mode chrome color.
53
+ * Browser + PWA `theme-color` / viewport meta colors, keyed by
54
+ * `prefers-color-scheme`. `dark` is aliased to {@link colors}`.hex.background`
55
+ * (not a re-typed copy) so the browser chrome always matches the dark page
56
+ * background exactly; `light` is a standalone light-mode chrome color with no
57
+ * palette counterpart. Hex, not oklch, because `<meta name="theme-color">`
58
+ * across browsers doesn't accept `oklch()`.
39
59
  */
40
60
  const themeColor = {
41
61
  light: "#E8EAF0",
42
62
  dark: colors.hex.background
43
63
  };
44
- /** Brand typefaces, ready-to-use CSS font stacks, and the webfont stylesheet. */
64
+ /**
65
+ * Brand typefaces, ready-to-use CSS font stacks, and the webfont stylesheet.
66
+ *
67
+ * Within each {@link fonts.stacks} array the **first** entry is the brand face
68
+ * and the rest are ordered fallbacks the browser walks until one resolves;
69
+ * multi-word family names are pre-quoted so the array can be joined into a
70
+ * `font-family` value verbatim. {@link fonts.googleFontsHref} must stay in sync
71
+ * with these families and the weights they're actually rendered at — a face or
72
+ * weight used in the app but missing from the href won't load.
73
+ */
45
74
  const fonts = {
46
75
  display: "Syne",
47
76
  body: "DM Sans",
package/lib/tokens.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","names":[],"sources":["../src/tokens.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * ResQ Systems design tokens the single source of truth shared by `@resq-systems/ui`,\n * `@resq-systems/email-templates`, and app surfaces.\n *\n * `oklch` is the design-system source of truth; `hex` is the email/legacy-safe\n * snapshot (email clients and older targets do not support `oklch()`). Keep the\n * two representations in sync when the palette changes.\n */\n/**\n * The six canonical color roles present in **both** representations. `oklch`\n * (the design-system source of truth) and `hex` (the email-safe snapshot) must\n * each define every one of these.\n */\nexport type ColorRole = \"background\" | \"surface\" | \"border\" | \"foreground\" | \"muted\" | \"primary\";\n\n/**\n * Status roles that exist only in the email-safe `hex` snapshot. `oklch` does\n * not define these, so they are indexable on `colors.hex` but never on\n * `colors.oklch`.\n */\nexport type StatusRole = \"info\" | \"success\" | \"warning\" | \"danger\";\n\nexport const colors = {\n\toklch: {\n\t\tbackground: \"oklch(16.63% 0.0262 269.37)\",\n\t\tsurface: \"oklch(19.72% 0.0231 268.80)\",\n\t\tborder: \"oklch(26.45% 0.0386 270.81)\",\n\t\tforeground: \"oklch(96.19% 0.0109 274.89)\",\n\t\tmuted: \"oklch(64.00% 0.0535 266.82)\",\n\t\tprimary: \"oklch(58.50% 0.1877 24.72)\",\n\t},\n\thex: {\n\t\tbackground: \"#0A0E1A\",\n\t\tsurface: \"#171C2B\",\n\t\tborder: \"#1E2438\",\n\t\tforeground: \"#F0F2FA\",\n\t\tmuted: \"#7D8CAE\",\n\t\tprimary: \"#D43E3F\",\n\t\tinfo: \"#7D8CAE\",\n\t\tsuccess: \"#3FB984\",\n\t\twarning: \"#E0A100\",\n\t\tdanger: \"#D43E3F\",\n\t},\n\t/**\n\t * Categorical data-visualization palette — the five `--chart-1..5` oklch\n\t * values shipped by `@resq-systems/ui` (canonical dark `:root` scale). Charts\n\t * cycle these in order for series colors. `oklch` only (not email-safe).\n\t */\n\tchart: [\n\t\t\"oklch(58.50% 0.1877 24.72)\",\n\t\t\"oklch(64.20% 0.1560 252.61)\",\n\t\t\"oklch(73.39% 0.1538 161.68)\",\n\t\t\"oklch(78.37% 0.1587 72.99)\",\n\t\t\"oklch(68.62% 0.0471 261.10)\",\n\t],\n} as const satisfies {\n\toklch: Record<ColorRole, `oklch(${string})`>;\n\thex: Record<ColorRole | StatusRole, `#${string}`>;\n\tchart: readonly `oklch(${string})`[];\n};\n\n/**\n * Roles indexable on `colors.oklch` — exactly {@link ColorRole}. Type any\n * lookup into the oklch source with this so a hex-only {@link StatusRole} can\n * never index it (which would type as `string` yet be `undefined` at runtime).\n */\nexport type OklchColorRole = keyof typeof colors.oklch;\n\n/** Every token name present on the email-safe `hex` snapshot. */\nexport type ColorTokenName = keyof typeof colors.hex;\n\n/**\n * Browser + PWA `theme-color` / viewport meta colors. `dark` tracks the\n * canonical page background; `light` is the light-mode chrome color.\n */\nexport const themeColor = {\n\tlight: \"#E8EAF0\",\n\tdark: colors.hex.background,\n} as const;\n\n/** Brand typefaces, ready-to-use CSS font stacks, and the webfont stylesheet. */\nexport const fonts = {\n\tdisplay: \"Syne\",\n\tbody: \"DM Sans\",\n\tmono: \"DM Mono\",\n\tstacks: {\n\t\tdisplay: [\"Syne\", \"'Helvetica Neue'\", \"Arial\", \"sans-serif\"],\n\t\tbody: [\n\t\t\t\"'DM Sans'\",\n\t\t\t\"-apple-system\",\n\t\t\t\"BlinkMacSystemFont\",\n\t\t\t\"'Segoe UI'\",\n\t\t\t\"Roboto\",\n\t\t\t\"Helvetica\",\n\t\t\t\"Arial\",\n\t\t\t\"sans-serif\",\n\t\t],\n\t\tmono: [\"'DM Mono'\", \"ui-monospace\", \"'SF Mono'\", \"Menlo\", \"Consolas\", \"monospace\"],\n\t},\n\tgoogleFontsHref:\n\t\t\"https://fonts.googleapis.com/css2?family=Syne:wght@700;800&family=DM+Sans:wght@400;500&family=DM+Mono:wght@500&display=swap\",\n} as const;\n\n/**\n * Border radius scale (px, email-safe). Mirrors the shipped `@resq-systems/ui`\n * `--radius-*` scale: `sm`→token (3px), `md`→control (4px), `lg`→panel (6px),\n * `xl` (panel + 4px = 10px). `full` is the pill radius (no UI counterpart).\n */\nexport const radii = {\n\tsm: \"3px\",\n\tmd: \"4px\",\n\tlg: \"6px\",\n\txl: \"10px\",\n\tfull: \"999px\",\n} as const;\n"],"mappings":";AAsCA,MAAa,SAAS;CACrB,OAAO;EACN,YAAY;EACZ,SAAS;EACT,QAAQ;EACR,YAAY;EACZ,OAAO;EACP,SAAS;CACV;CACA,KAAK;EACJ,YAAY;EACZ,SAAS;EACT,QAAQ;EACR,YAAY;EACZ,OAAO;EACP,SAAS;EACT,MAAM;EACN,SAAS;EACT,SAAS;EACT,QAAQ;CACT;;;;;;CAMA,OAAO;EACN;EACA;EACA;EACA;EACA;CACD;AACD;;;;;AAoBA,MAAa,aAAa;CACzB,OAAO;CACP,MAAM,OAAO,IAAI;AAClB;;AAGA,MAAa,QAAQ;CACpB,SAAS;CACT,MAAM;CACN,MAAM;CACN,QAAQ;EACP,SAAS;GAAC;GAAQ;GAAoB;GAAS;EAAY;EAC3D,MAAM;GACL;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACD;EACA,MAAM;GAAC;GAAa;GAAgB;GAAa;GAAS;GAAY;EAAW;CAClF;CACA,iBACC;AACF;;;;;;AAOA,MAAa,QAAQ;CACpB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;AACP"}
1
+ {"version":3,"file":"tokens.js","names":[],"sources":["../src/tokens.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview ResQ Systems design tokens (colors, theme colors, fonts, radii) —\n * the single source of truth shared by `@resq-systems/ui`,\n * `@resq-systems/email-templates`, and app surfaces. `oklch` is the design-system\n * source of truth; `hex` is the email/legacy-safe snapshot (email clients and\n * older targets do not support `oklch()`), so keep the two representations in sync\n * when the palette changes.\n *\n * @module @resq-systems/constants/tokens\n */\n\n/**\n * The six canonical color roles present in **both** representations. `oklch`\n * (the design-system source of truth) and `hex` (the email-safe snapshot) must\n * each define every one of these.\n *\n * These are semantic *roles*, not raw swatches: consumers reference\n * `colors.oklch.primary`, never the literal channel values, so a palette change\n * updates the token once. The union has no meaningful ordering — membership, not\n * position, is the contract.\n */\nexport type ColorRole = \"background\" | \"surface\" | \"border\" | \"foreground\" | \"muted\" | \"primary\";\n\n/**\n * Status roles that exist only in the email-safe `hex` snapshot. `oklch` does\n * not define these, so they are indexable on `colors.hex` but never on\n * {@link ColorRole} / `colors.oklch` — the type split enforces that asymmetry at\n * compile time. In apps these four states come from the `@resq-systems/ui`\n * theme's own status tokens rather than from here; the hex copies exist so\n * transactional email (which can't evaluate `oklch()`) still has them.\n */\nexport type StatusRole = \"info\" | \"success\" | \"warning\" | \"danger\";\n\n/**\n * The canonical palette in its two representations. `oklch` is the source of\n * truth; `hex` is a hand-maintained snapshot that must resolve to the same\n * perceived color for each shared {@link ColorRole}, because email clients and\n * older render targets can't evaluate `oklch()`. Editing one representation\n * without the other silently drifts email away from the app — the two are only\n * *structurally* linked by the `satisfies` clause below, not value-checked.\n *\n * @example\n * ```ts\n * import { colors } from \"@resq-systems/constants/tokens\";\n *\n * colors.oklch.primary; // → \"oklch(58.50% 0.1877 24.72)\"\n * colors.hex.danger; // → \"#D43E3F\" (status role — hex only)\n * ```\n */\nexport const colors = {\n\toklch: {\n\t\tbackground: \"oklch(16.63% 0.0262 269.37)\",\n\t\tsurface: \"oklch(19.72% 0.0231 268.80)\",\n\t\tborder: \"oklch(26.45% 0.0386 270.81)\",\n\t\tforeground: \"oklch(96.19% 0.0109 274.89)\",\n\t\tmuted: \"oklch(64.00% 0.0535 266.82)\",\n\t\tprimary: \"oklch(58.50% 0.1877 24.72)\",\n\t},\n\thex: {\n\t\tbackground: \"#0A0E1A\",\n\t\tsurface: \"#171C2B\",\n\t\tborder: \"#1E2438\",\n\t\tforeground: \"#F0F2FA\",\n\t\tmuted: \"#7D8CAE\",\n\t\tprimary: \"#D43E3F\",\n\t\tinfo: \"#7D8CAE\",\n\t\tsuccess: \"#3FB984\",\n\t\twarning: \"#E0A100\",\n\t\tdanger: \"#D43E3F\",\n\t},\n\t/**\n\t * Categorical data-visualization palette — the five `--chart-1..5` oklch\n\t * values shipped by `@resq-systems/ui` (canonical dark `:root` scale). Charts\n\t * cycle these in order for series colors. `oklch` only (not email-safe).\n\t */\n\tchart: [\n\t\t\"oklch(58.50% 0.1877 24.72)\",\n\t\t\"oklch(64.20% 0.1560 252.61)\",\n\t\t\"oklch(73.39% 0.1538 161.68)\",\n\t\t\"oklch(78.37% 0.1587 72.99)\",\n\t\t\"oklch(68.62% 0.0471 261.10)\",\n\t],\n} as const satisfies {\n\toklch: Record<ColorRole, `oklch(${string})`>;\n\thex: Record<ColorRole | StatusRole, `#${string}`>;\n\tchart: readonly `oklch(${string})`[];\n};\n\n/**\n * Roles indexable on `colors.oklch` — exactly {@link ColorRole}. Type any\n * lookup into the oklch source with this so a hex-only {@link StatusRole} can\n * never index it (which would type as `string` yet be `undefined` at runtime).\n */\nexport type OklchColorRole = keyof typeof colors.oklch;\n\n/** Every token name present on the email-safe `hex` snapshot. */\nexport type ColorTokenName = keyof typeof colors.hex;\n\n/**\n * Browser + PWA `theme-color` / viewport meta colors, keyed by\n * `prefers-color-scheme`. `dark` is aliased to {@link colors}`.hex.background`\n * (not a re-typed copy) so the browser chrome always matches the dark page\n * background exactly; `light` is a standalone light-mode chrome color with no\n * palette counterpart. Hex, not oklch, because `<meta name=\"theme-color\">`\n * across browsers doesn't accept `oklch()`.\n */\nexport const themeColor = {\n\tlight: \"#E8EAF0\",\n\tdark: colors.hex.background,\n} as const;\n\n/**\n * Brand typefaces, ready-to-use CSS font stacks, and the webfont stylesheet.\n *\n * Within each {@link fonts.stacks} array the **first** entry is the brand face\n * and the rest are ordered fallbacks the browser walks until one resolves;\n * multi-word family names are pre-quoted so the array can be joined into a\n * `font-family` value verbatim. {@link fonts.googleFontsHref} must stay in sync\n * with these families and the weights they're actually rendered at — a face or\n * weight used in the app but missing from the href won't load.\n */\nexport const fonts = {\n\tdisplay: \"Syne\",\n\tbody: \"DM Sans\",\n\tmono: \"DM Mono\",\n\tstacks: {\n\t\tdisplay: [\"Syne\", \"'Helvetica Neue'\", \"Arial\", \"sans-serif\"],\n\t\tbody: [\n\t\t\t\"'DM Sans'\",\n\t\t\t\"-apple-system\",\n\t\t\t\"BlinkMacSystemFont\",\n\t\t\t\"'Segoe UI'\",\n\t\t\t\"Roboto\",\n\t\t\t\"Helvetica\",\n\t\t\t\"Arial\",\n\t\t\t\"sans-serif\",\n\t\t],\n\t\tmono: [\"'DM Mono'\", \"ui-monospace\", \"'SF Mono'\", \"Menlo\", \"Consolas\", \"monospace\"],\n\t},\n\tgoogleFontsHref:\n\t\t\"https://fonts.googleapis.com/css2?family=Syne:wght@700;800&family=DM+Sans:wght@400;500&family=DM+Mono:wght@500&display=swap\",\n} as const;\n\n/**\n * Border radius scale (px, email-safe). Mirrors the shipped `@resq-systems/ui`\n * `--radius-*` scale: `sm`→token (3px), `md`→control (4px), `lg`→panel (6px),\n * `xl` (panel + 4px = 10px). `full` is the pill radius (no UI counterpart).\n */\nexport const radii = {\n\tsm: \"3px\",\n\tmd: \"4px\",\n\tlg: \"6px\",\n\txl: \"10px\",\n\tfull: \"999px\",\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;AAiEA,MAAa,SAAS;CACrB,OAAO;EACN,YAAY;EACZ,SAAS;EACT,QAAQ;EACR,YAAY;EACZ,OAAO;EACP,SAAS;CACV;CACA,KAAK;EACJ,YAAY;EACZ,SAAS;EACT,QAAQ;EACR,YAAY;EACZ,OAAO;EACP,SAAS;EACT,MAAM;EACN,SAAS;EACT,SAAS;EACT,QAAQ;CACT;;;;;;CAMA,OAAO;EACN;EACA;EACA;EACA;EACA;CACD;AACD;;;;;;;;;AAwBA,MAAa,aAAa;CACzB,OAAO;CACP,MAAM,OAAO,IAAI;AAClB;;;;;;;;;;;AAYA,MAAa,QAAQ;CACpB,SAAS;CACT,MAAM;CACN,MAAM;CACN,QAAQ;EACP,SAAS;GAAC;GAAQ;GAAoB;GAAS;EAAY;EAC3D,MAAM;GACL;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACD;EACA,MAAM;GAAC;GAAa;GAAgB;GAAa;GAAS;GAAY;EAAW;CAClF;CACA,iBACC;AACF;;;;;;AAOA,MAAa,QAAQ;CACpB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;AACP"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resq-systems/constants",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Shared, zero-dependency constants for ResQ Systems apps: design tokens (oklch + email-safe hex), brand identity, and cross-app values",
5
5
  "license": "Apache-2.0",
6
6
  "author": {
@@ -45,7 +45,7 @@
45
45
  "@total-typescript/ts-reset": "^0.6.1",
46
46
  "@types/node": "^26.1.1",
47
47
  "@vitest/coverage-v8": "4.1.10",
48
- "tsdown": "^0.22.4",
48
+ "tsdown": "^0.22.9",
49
49
  "typescript": "7.0.2",
50
50
  "vitest": "4.1.8"
51
51
  },