@exxatdesignux/ui 0.4.0 → 0.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,98 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - ### `@exxatdesignux/ui` — publish hygiene + smarter scaffolder
8
+
9
+ Three real bugs in the `0.4.0` tarball made first-run consumer installs
10
+ fail. All three are now fixed.
11
+ - **`tokens/hooks-index.json` ships.** The `exports` map declared
12
+ `"./tokens/hooks-index.json"` but the `files` array did not include
13
+ `tokens`, so the file was silently omitted from the published tarball.
14
+ Any `import "@exxatdesignux/ui/tokens/hooks-index.json"` (used by
15
+ `@exxatdesignux/eslint-plugin`'s `no-deprecated-tokens` rule and by
16
+ workspaces that read the token registry) blew up with
17
+ `MODULE_NOT_FOUND`. The `files` array now includes `tokens`.
18
+ - **No more `workspace:*` leaking into the published template.** The
19
+ scaffolder template was sync'd from `apps/web/package.json`, which
20
+ uses `workspace:*` for both `@exxatdesignux/ui` (correct, gets
21
+ rewritten to a real semver pin) and a handful of monorepo-internal
22
+ dev tools (`@exxatdesignux/eslint-plugin`, …) which are not published
23
+ on npm. The previous sync rewrote only the design-system line, so
24
+ every consumer install (`npm` / `pnpm` / `yarn`) crashed on the
25
+ leaked entries. The sync script now walks every dep map
26
+ (`dependencies` / `devDependencies` / `peerDependencies` /
27
+ `optionalDependencies`), pins `@exxatdesignux/ui`, deletes any
28
+ remaining `workspace:` value, and fails the build if any leaks
29
+ survive — so the bug surfaces here, not on a consumer's terminal.
30
+ - **Consumer-safe `eslint.config.mjs` in the template.** The repo's
31
+ own `apps/web/eslint.config.mjs` imports
32
+ `@exxatdesignux/eslint-plugin` for DS guardrails (no hex literals,
33
+ no deprecated tokens, no SLDS leakage, no Sonner toasts). Because
34
+ that plugin isn't published, `pnpm lint` in a freshly-scaffolded app
35
+ crashed with `Cannot find package '@exxatdesignux/eslint-plugin'`.
36
+ The sync script now overwrites `template/eslint.config.mjs` with a
37
+ clean `eslint-config-next + globalIgnores + unused-vars` setup that
38
+ every consumer can run. The DS guardrails graduate to this template
39
+ whenever the plugin lands on npm.
40
+
41
+ ### Smarter `bin/init.mjs` scaffolder
42
+
43
+ The `create-exxat-app` binary now matches the conventions of
44
+ `create-next-app` and `create-vite`:
45
+ - **Positional target directory.** `create-exxat-app my-app` creates
46
+ `./my-app` and scaffolds into it. `create-exxat-app .` scaffolds
47
+ into the current directory. Missing directories are auto-created.
48
+ - **Package-manager auto-detection.** Reads `npm_config_user_agent`
49
+ and runs the matching install (`pnpm install` / `yarn install` /
50
+ `bun install` / `npm install`). The post-install hint prints the
51
+ matching `<pm> run dev` command.
52
+ - **`--force` flag.** Allow scaffolding into a non-empty directory
53
+ (existing files are not overwritten unless the template ships the
54
+ same path). The previous "directory must be empty" hard-error
55
+ blocked every "install the DS first, then scaffold" sequence.
56
+ - **`--no-install` flag.** Skip the install step (useful in CI or
57
+ sandboxed setups).
58
+ - **`--help` / `-h`.** Print usage.
59
+ - **Clearer blocked-directory error.** When the target is non-empty
60
+ without `--force`, the CLI lists which files are blocking and
61
+ suggests both options (`create-exxat-app my-new-app` or
62
+ `create-exxat-app . --force`) instead of failing silently.
63
+
64
+ ### Real README on the npm package page
65
+
66
+ `packages/ui/` had no `README.md` — the npm landing page at
67
+ [npmjs.com/package/@exxatdesignux/ui](https://www.npmjs.com/package/@exxatdesignux/ui)
68
+ showed only the bare package.json description. The new README leads
69
+ with the 60-second start (`pnpm create exxat-app my-app`), covers
70
+ "adding to an existing Next.js app", documents `exxat-ui sync-extras`
71
+ for Cursor skill installation, and links the full doc set.
72
+
73
+ ### `create-exxat-app@0.0.x` → new package
74
+
75
+ A new `create-exxat-app` discovery package now ships on npm so
76
+ `pnpm create exxat-app my-app` (and the npm / yarn / bun variants)
77
+ resolve natively without a `--package=` flag. The shim is intentionally
78
+ tiny — it depends on `@exxatdesignux/ui` (via `workspace:^`, pinned to
79
+ `^<version>` at publish) and delegates to
80
+ `@exxatdesignux/ui/bin/init.mjs`. All template, version-pinning, and
81
+ package-manager-detection logic stays in `@exxatdesignux/ui` so there
82
+ is exactly one source of truth.
83
+
84
+ ### Migration
85
+
86
+ Consumers on `0.4.0` should bump to `0.4.1`:
87
+
88
+ ```bash
89
+ pnpm up @exxatdesignux/ui@latest
90
+ ```
91
+
92
+ If you scaffolded with `0.4.0` and edited `eslint.config.mjs` /
93
+ `package.json` to work around the workspace leak, you can either keep
94
+ your manual edits or re-scaffold with `0.4.1` for a clean baseline.
95
+
3
96
  ## 0.4.0
4
97
 
5
98
  ### Minor Changes
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # @exxatdesignux/ui
2
+
3
+ The Exxat Design System — a Next.js + React 19 + Tailwind v4 component
4
+ library plus the full hub-page stack (`ListPageTemplate`, `DataTable`,
5
+ `HubTable`, `TablePropertiesDrawer`, `KeyMetrics`, `PageHeader`, board
6
+ cards, charts, …) wrapped in one publishable package.
7
+
8
+ ## 60-second start
9
+
10
+ Spin up a brand-new app pre-wired with the DS:
11
+
12
+ ```bash
13
+ pnpm create exxat-app my-app
14
+ cd my-app
15
+ pnpm dev
16
+ ```
17
+
18
+ Works with every modern package manager — the scaffolder auto-detects
19
+ the runner and uses the matching install:
20
+
21
+ ```bash
22
+ npm create exxat-app my-app
23
+ yarn create exxat-app my-app
24
+ bun create exxat-app my-app
25
+ ```
26
+
27
+ The scaffolder ships a complete Next.js 16 starter: the reference
28
+ **Library** hub at `/library/all`, the `/columns` cell-catalog showcase,
29
+ typed mock data, the full Cursor skill + pattern doc set under
30
+ `cursor-rules/`, `cursor-skills/`, `patterns/`, and `handbook/`.
31
+
32
+ ## Adding to an existing Next.js app
33
+
34
+ If you already have a Next 15/16 app and just want the components:
35
+
36
+ ```bash
37
+ pnpm add @exxatdesignux/ui
38
+ ```
39
+
40
+ Then in your global CSS (e.g. `app/globals.css`):
41
+
42
+ ```css
43
+ @import "@exxatdesignux/ui/globals.css";
44
+ ```
45
+
46
+ And import primitives or full patterns from the umbrella or a subpath:
47
+
48
+ ```tsx
49
+ import { DataTable, HubTable, ListPageTemplate, KeyMetrics } from "@exxatdesignux/ui"
50
+ import { Button } from "@exxatdesignux/ui/components/button"
51
+ import { useTableState } from "@exxatdesignux/ui/components/data-table/use-table-state"
52
+ ```
53
+
54
+ Mount `KeyMetricsProvider` near the root if you want the "Ask Leo about
55
+ these metrics" CTA wired to your AI surface (otherwise the strip just
56
+ hides that button automatically).
57
+
58
+ ## Refresh Cursor skills + pattern docs in any consumer
59
+
60
+ The package ships a parallel set of binding rules, skills, and pattern
61
+ docs so AI agents in your own repo can read the same guidance the source
62
+ repo uses. To install or refresh them in your repo:
63
+
64
+ ```bash
65
+ pnpm dlx --package=@exxatdesignux/ui@latest exxat-ui sync-extras
66
+ ```
67
+
68
+ This copies `cursor-rules/`, `cursor-skills/`, `patterns/`, and
69
+ `handbook/` into your repo root. The next time Cursor opens, every
70
+ binding rule + skill is live.
71
+
72
+ ## What's inside
73
+
74
+ - **Primitives** (`@exxatdesignux/ui/components/<name>`) — Button, Input,
75
+ Select, Dialog, AlertDialog, Sheet, Drawer, Popover, DropdownMenu,
76
+ ContextMenu, Tabs, Accordion, Tooltip, Toast-free Banner, ScrollArea,
77
+ Slider, HoverCard, Avatar, Badge, StatusBadge, Calendar, Kbd, …
78
+ - **Hub stack** — `DataTable<TRow>`, `useTableState<TRow>`,
79
+ `TablePropertiesDrawer`, `HubTable<TRow>`, `ListPageTemplate`,
80
+ `PageHeader`, `KeyMetrics`, `ListPageBoardCard`,
81
+ `ListPageBoardTemplate`, `DataRowList`, `FinderPanelView`,
82
+ `FolderGridView`, `OutlineTreeMenu`.
83
+ - **Data-list registry** — `DataListViewType`, `DATA_LIST_VIEW_TILES`,
84
+ `dataListViewIcon`, `dataListViewAddShortcut`, `usesDataTableComponent`,
85
+ `usesDashboardSurface`.
86
+ - **Templates** — `ListPageTemplate`, `NestedSecondaryPanelShell`,
87
+ `DedicatedSearchLandingTemplate`, `DedicatedSearchResultsTemplate`.
88
+ - **Tokens** — `tokens/hooks-index.json` (197 tokens · 42 namespaces)
89
+ feeds the workspace ESLint plugin's `no-deprecated-tokens` rule.
90
+ - **Tailwind v4 token bridge** — `globals.css` imports the L0
91
+ `--exxat-color-*` / `--exxat-radius-*` / `--exxat-spacing-*` family
92
+ and wires Tailwind shorthand (`bg-surface-1`, `text-ink-1`,
93
+ `rounded-2`, …) via `@theme inline`.
94
+
95
+ ## CLI commands
96
+
97
+ After `pnpm add @exxatdesignux/ui` (or globally `npm i -g @exxatdesignux/ui`):
98
+
99
+ ```bash
100
+ # In an empty directory (or new sub-folder), scaffold an app:
101
+ npx --package=@exxatdesignux/ui create-exxat-app my-app
102
+
103
+ # Sync Cursor skills + binding rules + pattern docs into your repo:
104
+ npx --package=@exxatdesignux/ui exxat-ui sync-extras
105
+ ```
106
+
107
+ The standalone [`create-exxat-app`](https://www.npmjs.com/package/create-exxat-app)
108
+ package wraps the first command so `<pm> create exxat-app …` resolves
109
+ natively.
110
+
111
+ ## Docs
112
+
113
+ - Design-system **HANDBOOK** — read-this-first orientation, the 6-step
114
+ "how to build a hub" walkthrough, the §13 PR checklist.
115
+ - **Blueprints** — framework-agnostic specs for each major composition
116
+ (`PageHeader`, `DataTable`, `ListPageTemplate`, `BoardCard`,
117
+ `KeyMetrics`, …).
118
+ - **Component selection guide** — top-of-funnel decision tree for
119
+ picking the right composition.
120
+ - **Token taxonomy** — naming + deprecation policy for every CSS
121
+ custom property the DS ships.
122
+
123
+ The full doc set is mirrored under `handbook/` and `patterns/` in this
124
+ package; `exxat-ui sync-extras` drops them into your repo so they sit
125
+ alongside your source.
126
+
127
+ ## Compatibility
128
+
129
+ | Peer | Range |
130
+ | --- | --- |
131
+ | React | `>=19.0.0` |
132
+ | Next.js | `>=15.0.0` (App Router) |
133
+ | Tailwind CSS | `>=4.0.0` |
134
+ | Node | `>=22.0.0` (build / dev) |
135
+
136
+ ## License
137
+
138
+ UNLICENSED — proprietary to Exxat Design.
package/bin/init.mjs CHANGED
@@ -1,43 +1,146 @@
1
1
  #!/usr/bin/env node
2
- import { cpSync, readFileSync, readdirSync, writeFileSync } from 'fs'
3
- import { resolve, dirname } from 'path'
4
- import { fileURLToPath } from 'url'
5
- import { execSync } from 'child_process'
2
+ /**
3
+ * Scaffold a new Exxat DS app from the bundled template.
4
+ *
5
+ * Usage:
6
+ * npx create-exxat-app # scaffold into current directory
7
+ * npx create-exxat-app my-app # scaffold into ./my-app (created if missing)
8
+ * npx create-exxat-app . --force # overwrite-merge into current directory
9
+ * npx create-exxat-app my-app --no-install # skip the package install step
10
+ *
11
+ * Also runs as `npx --package=@exxatdesignux/ui create-exxat-app …` and as
12
+ * `pnpm create exxat-app …` when invoked via the standalone create-exxat-app
13
+ * discovery shim.
14
+ */
15
+ import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs"
16
+ import { resolve, dirname, basename, join } from "node:path"
17
+ import { fileURLToPath } from "node:url"
18
+ import { execSync } from "node:child_process"
6
19
 
7
20
  const __dirname = dirname(fileURLToPath(import.meta.url))
8
- const templateDir = resolve(__dirname, '../template')
9
- const selfPkgPath = resolve(__dirname, '../package.json')
10
- const targetDir = process.cwd()
21
+ const templateDir = resolve(__dirname, "../template")
22
+ const selfPkgPath = resolve(__dirname, "../package.json")
23
+ const selfPkg = JSON.parse(readFileSync(selfPkgPath, "utf8"))
11
24
 
12
- const files = readdirSync(targetDir)
13
- const isEmpty = files.length === 0 || (files.length === 1 && files[0] === '.git')
25
+ const args = process.argv.slice(2)
26
+ const flags = new Set(args.filter((a) => a.startsWith("--")))
27
+ const positional = args.filter((a) => !a.startsWith("--"))
28
+ const targetArg = positional[0] ?? "."
29
+ const targetDir = resolve(process.cwd(), targetArg)
30
+ const projectName = targetArg === "." ? basename(targetDir) : targetArg
31
+ const force = flags.has("--force")
32
+ const skipInstall = flags.has("--no-install") || flags.has("--skip-install")
14
33
 
15
- if (!isEmpty) {
16
- console.error('❌ Target directory is not empty. Run this in a new empty folder.')
34
+ if (flags.has("--help") || flags.has("-h")) {
35
+ console.log(`
36
+ create-exxat-app — scaffold a Next.js app on @exxatdesignux/ui
37
+
38
+ Usage:
39
+ create-exxat-app [target-directory] [options]
40
+
41
+ Arguments:
42
+ target-directory Where to create the app (default: ".")
43
+ A relative or absolute path. Created if it does not exist.
44
+
45
+ Options:
46
+ --force Allow scaffolding into a non-empty directory (existing
47
+ files are NOT overwritten unless template ships the
48
+ same path).
49
+ --no-install Skip the dependency install step.
50
+ -h, --help Show this message.
51
+
52
+ Examples:
53
+ create-exxat-app my-app
54
+ create-exxat-app .
55
+ create-exxat-app ../sandbox --force --no-install
56
+ `)
57
+ process.exit(0)
58
+ }
59
+
60
+ if (!existsSync(targetDir)) {
61
+ mkdirSync(targetDir, { recursive: true })
62
+ console.log(`📁 Created ${projectName}/`)
63
+ }
64
+
65
+ const targetStat = statSync(targetDir)
66
+ if (!targetStat.isDirectory()) {
67
+ console.error(`❌ Target ${targetDir} exists but is not a directory.`)
17
68
  process.exit(1)
18
69
  }
19
70
 
20
- console.log('📦 Copying Exxat DS starter app...')
71
+ const existing = readdirSync(targetDir)
72
+ const ignorable = new Set([".git", ".gitignore", ".DS_Store"])
73
+ const blockers = existing.filter((name) => !ignorable.has(name))
74
+
75
+ if (blockers.length > 0 && !force) {
76
+ console.error(`❌ Target directory is not empty (${targetDir}).`)
77
+ console.error("")
78
+ console.error(" Found:")
79
+ for (const name of blockers.slice(0, 8)) console.error(` - ${name}`)
80
+ if (blockers.length > 8) console.error(` … and ${blockers.length - 8} more`)
81
+ console.error("")
82
+ console.error(" Options:")
83
+ console.error(` 1. Scaffold into a new folder: create-exxat-app my-app`)
84
+ console.error(` 2. Allow merging existing files: create-exxat-app . --force`)
85
+ console.error("")
86
+ process.exit(1)
87
+ }
88
+
89
+ console.log(`📦 Copying Exxat DS starter app into ${projectName}/ …`)
21
90
  cpSync(templateDir, targetDir, { recursive: true })
22
91
 
23
- /** Pin DS to this CLI tarball version so `npm install` does not resolve a stale `latest` from cache. */
24
- const selfVersion = JSON.parse(readFileSync(selfPkgPath, 'utf8')).version
25
- const targetPkgPath = resolve(targetDir, 'package.json')
26
- const targetPkg = JSON.parse(readFileSync(targetPkgPath, 'utf8'))
27
- if (targetPkg.dependencies?.['@exxatdesignux/ui']) {
28
- targetPkg.dependencies['@exxatdesignux/ui'] = `^${selfVersion}`
29
- writeFileSync(targetPkgPath, `${JSON.stringify(targetPkg, null, 2)}\n`)
30
- console.log(`📌 Pinned @exxatdesignux/ui to ^${selfVersion} (matches this scaffold).`)
92
+ // Pin DS to this CLI's published version so `latest` cache drift cannot
93
+ // trick the consumer into installing an older dist.
94
+ const targetPkgPath = resolve(targetDir, "package.json")
95
+ const targetPkg = JSON.parse(readFileSync(targetPkgPath, "utf8"))
96
+ if (targetPkg.dependencies?.["@exxatdesignux/ui"]) {
97
+ targetPkg.dependencies["@exxatdesignux/ui"] = `^${selfPkg.version}`
31
98
  }
99
+ // Name the project after the target dir for nicer dev-server / process titles.
100
+ targetPkg.name = projectName.replace(/[^a-z0-9-_]/gi, "-").toLowerCase() || "my-exxat-app"
101
+ writeFileSync(targetPkgPath, `${JSON.stringify(targetPkg, null, 2)}\n`)
102
+ console.log(`📌 Pinned @exxatdesignux/ui to ^${selfPkg.version} and named the project "${targetPkg.name}".`)
32
103
 
33
- console.log('📥 Installing dependencies...')
34
- execSync('npm install', { stdio: 'inherit', cwd: targetDir })
35
-
36
- console.log('')
37
- console.log('✅ Done! Your Exxat DS app is ready.')
38
- console.log('')
39
- console.log(' npm run dev → start dev server')
40
- console.log('')
41
- console.log(' Optional — refresh Cursor skills + pattern docs from the same package:')
42
- console.log(` npx --package=@exxatdesignux/ui@${selfVersion} exxat-ui sync-extras`)
43
- console.log('')
104
+ const pm = detectPackageManager()
105
+ if (skipInstall) {
106
+ console.log(`⏭ Skipped install (--no-install).`)
107
+ } else {
108
+ console.log(`📥 Installing dependencies with ${pm.label} …`)
109
+ try {
110
+ execSync(pm.installCmd, { stdio: "inherit", cwd: targetDir })
111
+ } catch (err) {
112
+ console.error("")
113
+ console.error(`❌ ${pm.label} install failed. You can retry manually:`)
114
+ console.error(` cd ${projectName} && ${pm.installCmd}`)
115
+ process.exit(1)
116
+ }
117
+ }
118
+
119
+ console.log("")
120
+ console.log(`✅ Done! Your Exxat DS app is ready in ./${projectName}/`)
121
+ console.log("")
122
+ console.log(` cd ${projectName}`)
123
+ console.log(` ${pm.runCmd} dev # start dev server`)
124
+ console.log("")
125
+ console.log(" Optional — refresh Cursor skills + pattern docs:")
126
+ console.log(` ${pm.dlxCmd} --package=@exxatdesignux/ui@${selfPkg.version} exxat-ui sync-extras`)
127
+ console.log("")
128
+
129
+ /**
130
+ * Detect the package manager that invoked us — npm_config_user_agent is set
131
+ * by every modern package-runner (npm, pnpm, yarn, bun) and looks like
132
+ * "pnpm/10.33.0 npm/? node/v22.0.0 darwin arm64". We fall back to npm.
133
+ */
134
+ function detectPackageManager() {
135
+ const ua = process.env.npm_config_user_agent ?? ""
136
+ if (ua.startsWith("pnpm")) {
137
+ return { label: "pnpm", installCmd: "pnpm install", runCmd: "pnpm", dlxCmd: "pnpm dlx" }
138
+ }
139
+ if (ua.startsWith("yarn")) {
140
+ return { label: "yarn", installCmd: "yarn install", runCmd: "yarn", dlxCmd: "yarn dlx" }
141
+ }
142
+ if (ua.startsWith("bun")) {
143
+ return { label: "bun", installCmd: "bun install", runCmd: "bun", dlxCmd: "bunx" }
144
+ }
145
+ return { label: "npm", installCmd: "npm install", runCmd: "npm run", dlxCmd: "npx" }
146
+ }
@@ -4,7 +4,7 @@ import * as React from 'react';
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const systemBannerVariants: (props?: ({
7
- variant?: "error" | "success" | "warning" | "info" | "promo" | null | undefined;
7
+ variant?: "success" | "warning" | "error" | "info" | "promo" | null | undefined;
8
8
  emphasis?: "prominent" | "subtle" | null | undefined;
9
9
  actionPosition?: "inline" | "bottom" | null | undefined;
10
10
  } & class_variance_authority_types.ClassProp) | undefined) => string;
@@ -32,7 +32,7 @@ interface SystemBannerProps extends React.HTMLAttributes<HTMLDivElement>, Varian
32
32
  }
33
33
  declare function SystemBanner({ children, title, variant, emphasis, dismissible, onDismiss, action, actionPosition, icon, decorativeOverlay, className, style, ...props }: SystemBannerProps): react_jsx_runtime.JSX.Element | null;
34
34
  declare const localBannerVariants: (props?: ({
35
- variant?: "error" | "success" | "warning" | "info" | "promo" | null | undefined;
35
+ variant?: "success" | "warning" | "error" | "info" | "promo" | null | undefined;
36
36
  } & class_variance_authority_types.ClassProp) | undefined) => string;
37
37
  interface LocalBannerProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof localBannerVariants> {
38
38
  /** Banner title (optional) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exxatdesignux/ui",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Exxat shared design system (components, hooks, tokens). Monorepo setup: clone repo then pnpm bootstrap at workspace root — see github.com/ExxatDesign/Exxat-DS-Workspace README.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Exxat Design",
@@ -98,7 +98,8 @@
98
98
  "src",
99
99
  "bin",
100
100
  "template",
101
- "consumer-extras"
101
+ "consumer-extras",
102
+ "tokens"
102
103
  ],
103
104
  "dependencies": {
104
105
  "@hookform/resolvers": "^5.2.2",
@@ -1,14 +1,15 @@
1
- import { defineConfig, globalIgnores } from "eslint/config";
2
- import nextVitals from "eslint-config-next/core-web-vitals";
3
- import nextTs from "eslint-config-next/typescript";
4
- import exxatDs from "@exxatdesignux/eslint-plugin";
1
+ import { defineConfig, globalIgnores } from "eslint/config"
2
+ import nextVitals from "eslint-config-next/core-web-vitals"
3
+ import nextTs from "eslint-config-next/typescript"
5
4
 
5
+ // Consumer-facing ESLint config for a scaffolded Exxat DS app.
6
+ // The Exxat-DS guardrail plugin (`@exxatdesignux/eslint-plugin`) is
7
+ // currently workspace-internal — once it lands on npm you can add it
8
+ // alongside the blocks below and the same DS lint rules will run here.
6
9
  const eslintConfig = defineConfig([
7
10
  ...nextVitals,
8
11
  ...nextTs,
9
- // Override default ignores of eslint-config-next.
10
12
  globalIgnores([
11
- // Default ignores of eslint-config-next:
12
13
  ".next/**",
13
14
  "out/**",
14
15
  "build/**",
@@ -16,11 +17,6 @@ const eslintConfig = defineConfig([
16
17
  ]),
17
18
  {
18
19
  rules: {
19
- // Allow intentionally-unused args / vars / destructured props /
20
- // generics when prefixed with `_`. This is the standard escape hatch
21
- // for "I'm satisfying a callback signature but don't need this slot"
22
- // — common in cell renderers (`(value, _row) => …`), destructured
23
- // tuples (`const [_, setX] = useState()`), and generic constraints.
24
20
  "@typescript-eslint/no-unused-vars": [
25
21
  "warn",
26
22
  {
@@ -32,32 +28,6 @@ const eslintConfig = defineConfig([
32
28
  ],
33
29
  },
34
30
  },
35
- // -------------------------------------------------------------------------
36
- // Exxat DS guardrails (@exxatdesignux/eslint-plugin — packages/eslint-plugin-exxat-ds).
37
- // - no-hex-color: token discipline (no hex literals in JSX/style)
38
- // - no-deprecated-tokens: reads @exxatdesignux/ui tokens/hooks-index.json
39
- // - no-sonner-toast: enforces .cursor/rules/exxat-no-toast.mdc
40
- // - no-slds-classes: enforces .cursor/rules/exxat-no-slds-leakage.mdc
41
- // - no-lightning-elements: enforces .cursor/rules/exxat-no-slds-leakage.mdc
42
- // -------------------------------------------------------------------------
43
- {
44
- files: ["app/**/*.{ts,tsx}", "components/**/*.{ts,tsx}", "lib/**/*.{ts,tsx}", "hooks/**/*.{ts,tsx}", "contexts/**/*.{ts,tsx}", "stores/**/*.{ts,tsx}"],
45
- plugins: { "exxat-ds": exxatDs },
46
- rules: {
47
- "exxat-ds/no-hex-color": [
48
- "warn",
49
- {
50
- // Files where hex is legitimately needed (CSS variable definitions,
51
- // OS theme-color meta, etc.) are intentionally excluded by path.
52
- allowFiles: ["/app/globals.css", "/packages/ui/src/globals.css", "/lib/theme-color", "/lib/windows-contrast-theme"],
53
- },
54
- ],
55
- "exxat-ds/no-deprecated-tokens": "error",
56
- "exxat-ds/no-sonner-toast": "error",
57
- "exxat-ds/no-slds-classes": "error",
58
- "exxat-ds/no-lightning-elements": "error",
59
- },
60
- },
61
- ]);
31
+ ])
62
32
 
63
- export default eslintConfig;
33
+ export default eslintConfig
@@ -60,7 +60,6 @@
60
60
  },
61
61
  "devDependencies": {
62
62
  "@eslint/eslintrc": "^3",
63
- "@exxatdesignux/eslint-plugin": "workspace:*",
64
63
  "@next/bundle-analyzer": "16.2.6",
65
64
  "@tailwindcss/postcss": "^4.2.1",
66
65
  "@testing-library/jest-dom": "^6.9.1",