@dropins/tools 2.0.0-beta.1 → 2.0.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/CHANGELOG.md +125 -0
- package/lib/aem/assets.js +1 -1
- package/lib/aem/configs.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,130 @@
|
|
|
1
1
|
# @adobe-commerce/elsie
|
|
2
2
|
|
|
3
|
+
## 2.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- ea02d5f: Upgrade Jest to 30.4.2 and Storybook to 10.4.0
|
|
8
|
+
|
|
9
|
+
Updated testing and component development tools to latest stable versions. Jest 30.4.2 provides enhanced snapshot handling and improved test performance. Storybook 10.4.0 includes updated addon ecosystem, improved Preact Vite integration, and enhanced accessibility features with addon-a11y and addon-coverage support.
|
|
10
|
+
|
|
11
|
+
- 9cd299b: Upgrade TypeScript to 6.0 and ESLint to 9 (flat config)
|
|
12
|
+
|
|
13
|
+
## What changed
|
|
14
|
+
|
|
15
|
+
### TypeScript 4.7 → 6.0
|
|
16
|
+
|
|
17
|
+
- `tsconfig-base.json` updated with correct TS 6 defaults. Two new-default opt-outs are deferred as tech debt: `exactOptionalPropertyTypes` and `verbatimModuleSyntax`.
|
|
18
|
+
- `moduleResolution` changed from `"nodenext"` to `"bundler"` across all packages — the correct pairing for `module: "esnext"` in a Vite monorepo. Only `packages/elsie` keeps `"NodeNext"` (paired with `module: "NodeNext"` for its dual CJS/ESM output).
|
|
19
|
+
- `baseUrl` removed from all tsconfigs (deprecated in TS 6; `paths` resolves relative to the tsconfig file directly).
|
|
20
|
+
- `rootDir` added explicitly to `build-tools`, `event-bus`, `fetch-graphql`, and `recaptcha` tsconfigs (implicit `rootDir` deprecated in TS 6).
|
|
21
|
+
- `types: []` set in `tsconfig-base.json` to prevent ambient test types from leaking into declaration output. Each package's own `tsconfig.json` declares its `types` explicitly (`jest`, `node`, `vite/client`, etc.).
|
|
22
|
+
- `babel-plugin-tsconfig-paths` removed — it was a no-op in every package that listed it.
|
|
23
|
+
- `noUncheckedIndexedAccess` enabled — violations were few enough to fix in source.
|
|
24
|
+
|
|
25
|
+
### ESLint 8 → 9 (flat config)
|
|
26
|
+
|
|
27
|
+
- `@typescript-eslint/parser` and `@typescript-eslint/eslint-plugin` (v5) removed; replaced by the unified `typescript-eslint` v8 package.
|
|
28
|
+
- `eslint-config-preact` bumped to `^2.0.0` (ESLint 9 support).
|
|
29
|
+
- `eslint-config-prettier` bumped to `^10.0.0`.
|
|
30
|
+
- `eslint-plugin-mdx` bumped to `^3.8.1`. **ESLint 10 is not supported** — `eslint-plugin-mdx` vendors an internal ESLint API removed in v10; ESLint 9 is pinned until a fix is released.
|
|
31
|
+
- `globals` added (`^15.0.0`) for `languageOptions.globals` in flat config.
|
|
32
|
+
- Shared config (`packages/elsie/config/eslint.mjs`) rewritten as a flat-config array export.
|
|
33
|
+
- Per-package `.eslintrc.js` files deleted; replaced with `eslint.config.js` (ESM flat config).
|
|
34
|
+
- Several `typescript-eslint` v8 rules disabled to preserve prior behavior: `no-explicit-any`, `ban-ts-comment`, `no-unused-expressions`, `no-unsafe-function-type`, `no-require-imports`, `no-empty-object-type`. Tracked as tech debt.
|
|
35
|
+
- `reportUnusedDisableDirectives` disabled to avoid sweeping pre-existing inline disable comments.
|
|
36
|
+
|
|
37
|
+
### `vite-plugin-dts` removed; replaced with custom `dtsPlugin`
|
|
38
|
+
|
|
39
|
+
`vite-plugin-dts@3.9.1` declared a `typescript <5.0` peer range and its v5 successor was incompatible with this monorepo's layout (cross-package sources, workspace symlinks, multi-`outDir`). It was removed and replaced with a thin custom Vite plugin at `packages/elsie/config/plugins/dts.mjs` (`dtsPlugin`) that runs `tsc` directly. The resulting `dist/` layout is identical to what v3.9 produced (147 `.d.ts` files, 12 top-level entry shims).
|
|
40
|
+
|
|
41
|
+
### Module format standardization
|
|
42
|
+
|
|
43
|
+
All tooling config files now follow a consistent format:
|
|
44
|
+
|
|
45
|
+
- **ESLint / Jest / Vite configs** — ESM (`.js` in `"type":"module"` packages; `.mjs` in elsie).
|
|
46
|
+
- **Prettier** — JSON only (`@adobe-commerce/elsie/config/prettier.json` referenced via each package's `"prettier"` key). `prettier.config.*` files deleted from all packages.
|
|
47
|
+
- **elsie CLI** (`bin/**`) — intentionally stays CommonJS.
|
|
48
|
+
|
|
49
|
+
See `architecture/decisions/009-module-format.md` for the full convention.
|
|
50
|
+
|
|
51
|
+
### `.elsie.js` → `.elsie.cjs`
|
|
52
|
+
|
|
53
|
+
The consumer project config file is renamed from `.elsie.js` to `.elsie.cjs`. With `"type":"module"` now required in consumer packages, a plain `.js` file is treated as ES module — making `module.exports` a SyntaxError and making `require()` in the elsie CLI fail with `ERR_REQUIRE_ESM`. The `.cjs` extension forces CommonJS regardless of the package's `"type"` field.
|
|
54
|
+
|
|
55
|
+
- `elsie generate config` now writes `.elsie.cjs`.
|
|
56
|
+
- The CLI (`bin/lib/config.js`) and `config/vite.mjs` both prefer `.elsie.cjs` and fall back to `.elsie.js` for packages not yet migrated.
|
|
57
|
+
- `.elsie.cjs` added to `.npmignore` in all consumer packages.
|
|
58
|
+
|
|
59
|
+
## Consumer migration
|
|
60
|
+
|
|
61
|
+
See `docs/elsie-v2-migration.md` for the full step-by-step guide. Key actions:
|
|
62
|
+
|
|
63
|
+
1. Add `"type": "module"` to `package.json`.
|
|
64
|
+
2. Replace `.eslintrc.js` with `eslint.config.js` (ESM flat config importing from `@adobe-commerce/elsie/config/eslint.mjs`).
|
|
65
|
+
3. Rename `.elsie.js` → `.elsie.cjs` (keep `module.exports` content as-is).
|
|
66
|
+
4. Add `"prettier": "@adobe-commerce/elsie/config/prettier.json"` to `package.json`; delete `prettier.config.js`.
|
|
67
|
+
5. Update `tsconfig.json`: remove `baseUrl`, add explicit `rootDir` and `types`.
|
|
68
|
+
6. Add `tsconfig.build.json` for declaration emit (required by `dtsPlugin`).
|
|
69
|
+
7. Convert `.elsie.js` imports in `.storybook/main.js` and `storybook-stories.js` to reference `.elsie.cjs`.
|
|
70
|
+
|
|
71
|
+
### Minor Changes
|
|
72
|
+
|
|
73
|
+
- c21a378: Add optional `cypress` export to shared ESLint config
|
|
74
|
+
|
|
75
|
+
`cypress` is a new named export from `@adobe-commerce/elsie/config/eslint.mjs` that provides a pre-configured ESLint flat config for Cypress test files (`cypress/**/*.js`). It applies `eslint-plugin-cypress`'s recommended rules with `jest/expect-expect` turned off.
|
|
76
|
+
|
|
77
|
+
The plugin is declared as an optional peer dependency — `cypress` resolves to an empty array when `eslint-plugin-cypress` is not installed, so projects that don't use Cypress are unaffected.
|
|
78
|
+
|
|
79
|
+
## Usage
|
|
80
|
+
|
|
81
|
+
Install the peer dependency in your project:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
yarn add -D eslint-plugin-cypress
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Then spread `cypress` into your ESLint config:
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
import base, {
|
|
91
|
+
sourceImportRestrictions,
|
|
92
|
+
cypress,
|
|
93
|
+
} from '@adobe-commerce/elsie/config/eslint.mjs';
|
|
94
|
+
|
|
95
|
+
export default [...base, ...cypress, ...sourceImportRestrictions];
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- 9d558ed: Adds `window.DROPINS.showOverlays(state)` — a developer utility that visually outlines all dropin containers and slots on the page with labeled overlays, making it easier to understand how the storefront is composed at runtime.
|
|
99
|
+
|
|
100
|
+
`DROPINS.showSlots()` is deprecated in favor of `showOverlays()` and will log a console warning when called.
|
|
101
|
+
|
|
102
|
+
- c25a5d7: feat(elsie): add `changeset` builder command
|
|
103
|
+
|
|
104
|
+
Adds `elsie changeset` as a first-class CLI command, wrapping `@changesets/cli`. All subcommands pass through transparently (`status`, `version`, `publish`, `--snapshot`, etc.). `@changesets/cli` is now a dependency of elsie, so consumers no longer need to install it separately.
|
|
105
|
+
|
|
106
|
+
- 005edc7: Adds validation to the Incrementer component when the field is changed to "empty".
|
|
107
|
+
|
|
108
|
+
### Patch Changes
|
|
109
|
+
|
|
110
|
+
- bf352d2: Fix InputDate showing wrong format after selecting a date from the calendar
|
|
111
|
+
- 4c3d82d: fix(field): associate error messages with inputs via aria-describedby (WCAG 3.3.1)
|
|
112
|
+
- 36354d9: Add disableWhenSingle prop to Picker; defaults to true (preserves existing behavior). Pass false to keep the picker interactive when only one option is available.
|
|
113
|
+
- 09c2100: Declare `preact` as a runtime dependency. It previously sat in `devDependencies` (unlike `@preact/signals` and `preact-i18n`), so standalone consumers of `@adobe-commerce/elsie` had an unmet `preact` — also the unmet peer of `@preact/preset-vite`, `@storybook/preact-vite` and `@testing-library/preact`. It now resolves to the same `~10.22.1` bundled into `@dropins/tools`. The emitted bundle is unchanged.
|
|
114
|
+
- 4641ab0: Fix `Field` and `InLineAlert` status/error messages not being announced by screen readers. `Field`'s description/hint element now always carries `role="status"` and `aria-live="polite"`, instead of only adding `aria-live` once an error appeared, so assistive technology reliably announces validation and success messages (WCAG 4.1.3). `InLineAlert` now sets `role="alert"`/`aria-live="assertive"` for `type="error"` and `role="status"`/`aria-live="polite"` for `success`/`warning`, since it previously had no live-region semantics at all.
|
|
115
|
+
- ccada8c: Reset default margin on Header and CartItem titles to support rendering them as semantic headings
|
|
116
|
+
- cb6eb81: Fix `InLineAlert` additional-action buttons announcing the same accessible name across multiple alerts. Each entry in `additionalActions` may now include an optional `'aria-label'` that is applied to the rendered button (falling back to `label` when omitted), so consumers can give visually identical "Undo"/"Dismiss" style buttons unique, descriptive names for assistive technology.
|
|
117
|
+
- ab5cf32: Fix `Modal` accessibility: the dialog now exposes `role="dialog"`, `aria-modal="true"`, and an `aria-labelledby` linked to its title. Focus moves into the modal when it opens (falling back to the dialog body when there are no focusable elements), Tab/Shift+Tab now cycles between the first and last focusable elements instead of escaping the modal, and focus returns to the previously focused element when the modal closes.
|
|
118
|
+
- 58da630: Fix `Picker` accessible name and label association. The `<select>` now falls back to `floatingLabel` or `placeholder` for its `aria-label` when no `name` is provided, and the floating `<label>` is now correctly associated with the rendered `<select>` via its generated id instead of the raw `id` prop.
|
|
119
|
+
- 450c408: fix(Picker): auto-select and emit the sole option when the control auto-disables, so single-option narrowing on configurable PDPs no longer leaves the value unselected and Add to Cart permanently disabled
|
|
120
|
+
- 33ebe8a: Add accessible labels to password validation and input status icons (WCAG 1.1.1)
|
|
121
|
+
- 2ad7316: Fix `ToggleButton`'s underlying radio input announcing the shared radio-group `name` (e.g. "payment-method") as its accessible name for every option instead of the option's own visible label, which violates WCAG 2.4.6 (Headings and Labels) and 2.5.3 (Label in Name). The radio input's accessible name now defaults to `aria-labelledby` pointing at the option's own visible label content (e.g. "Check / Money order"), which works correctly whether `label` is a string or a `VNode`. An optional `ariaLabel` prop is still available for consumers who need to set an explicit accessible name via `aria-label` instead.
|
|
122
|
+
- 256007e: Fix ToggleButton generating invalid HTML ids when value prop contains spaces, breaking aria-labelledby label association
|
|
123
|
+
- 016a558: Fix low-contrast field label text in `Input` when a field is in an error state. The floating label color now meets WCAG AA contrast requirements for normal-size text against light backgrounds, matching the color already used for error text elsewhere (helper text, alerts).
|
|
124
|
+
- 51fcb35: fix(a11y): darken low-contrast focus indicators to meet WCAG 1.4.11 (3:1 non-text contrast)
|
|
125
|
+
|
|
126
|
+
The default keyboard focus indicator across Button, IconButton, Checkbox, RadioButton, ActionButton, ActionButtonGroup, ToggleButton, TextSwatch, ColorSwatch, ImageSwatch, and links used `--color-neutral-400` (#d6d6d6, ~1.45:1 against white), below the 3:1 minimum required by WCAG 1.4.11. These focus indicators now use `--color-neutral-600` (#8f8f8f, ~3.2:1), so keyboard users can reliably see which control is focused.
|
|
127
|
+
|
|
3
128
|
## 2.0.0-beta.1
|
|
4
129
|
|
|
5
130
|
### Patch Changes
|
package/lib/aem/assets.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/*! Copyright 2026 Adobe
|
|
2
2
|
All Rights Reserved. */
|
|
3
|
-
import{getConfigValue as O}from"./configs.js";import{p as f,I as g}from"../../chunks/Image.js";import"../../chunks/
|
|
3
|
+
import{getConfigValue as O}from"./configs.js";import{p as f,I as g}from"../../chunks/Image.js";import"../../chunks/get-path-value.js";import"../../chunks/cjs.js";import"../../chunks/preact-vendor.js";import"../../chunks/vcomponent.js";import"../../chunks/image-params-keymap.js";import"../../signals.js";const b=["gif","jpg","jpeg","png","webp"],v=[90,180,270],U=["h","v","hv"];function l(e){let t=e;if(t.startsWith("//")){const{protocol:s}=window.location;t=s+t}return t}function I(e){return U.includes(e)}function L(e){return v.includes(e)}function y(e){return b.includes(e)}function u(e,t,s){if(e!==void 0&&!t(e))throw new Error(s)}function h(){const e=O("commerce-assets-enabled");return e&&(typeof e=="string"&&e.toLowerCase()==="true"||typeof e=="boolean"&&e===!0)}function R(){return{quality:80,format:"webp"}}function A(e){return!!(typeof e=="string"?new URL(l(e)):e).pathname.startsWith("/adobe/assets/urn:aaid:aem")}function w(e,t,s={}){const r={...R(),...s},{format:i,crop:n,...o}=r;u(i,y,"Invalid format"),u(o.flip,I,"Invalid flip"),u(o.rotate,L,"Invalid rotation");const a=Object.fromEntries(Object.entries(o).map(([p,d])=>[p,String(d)])),c=new URLSearchParams(a);if(n){const[p,d]=[n.xOrigin||0,n.yOrigin||0],[P,E]=[n.width||100,n.height||100],S=`${p}p,${d}p,${P}p,${E}p`;c.set("crop",S)}return`${e}/as/${t}.${i}?${c.toString()}`}function M(e,t,s={}){if(!h())return e;const r=new URL(l(e));if(!A(r))return e;const i=r.origin+r.pathname;return w(i,t,s)}function _(e){return t=>{const{wrapper:s,alias:m,params:r,imageProps:i}=e;if(!i.src)throw new Error("An image source is required. Please provide a `src` or `imageProps.src`.");const n=s??document.createElement("div"),o=w(i.src,m,r),a={width:r.width,height:r.height,crop:void 0,fit:void 0,auto:void 0},c={...i,width:r.width,height:r.height,src:o,params:a};f.render(g,c)(n),t.replaceWith(n)}}function V(e,t){function s(){const i=t.wrapper??document.createElement("div"),{imageProps:n,params:o}=t,a={...n,width:o.width,height:o.height};f.render(g,a)(i),e.replaceWith(i)}if(!h()){s();return}if(!t.imageProps.src)throw new Error("An image source is required. Please provide a `src` or `imageProps.src`.");const r=new URL(l(t.imageProps.src));if(!A(r)){s();return}_(t)(e)}export{w as generateAemAssetsOptimizedUrl,R as getDefaultAemAssetsOptimizationParams,h as isAemAssetsEnabled,A as isAemAssetsUrl,_ as makeAemAssetsImageSlot,M as tryGenerateAemAssetsOptimizedUrl,V as tryRenderAemAssetsImage};
|
|
4
4
|
//# sourceMappingURL=assets.js.map
|
package/lib/aem/configs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/*! Copyright 2026 Adobe
|
|
2
2
|
All Rights Reserved. */
|
|
3
|
-
import{
|
|
3
|
+
import{g as c}from"../../chunks/get-path-value.js";import{d as s}from"../../chunks/cjs.js";let l=null,f=null,u=null,i=null;function z(){l=null,f=null,u=null,i=null}function g(t=l,e=f){return t?Object.keys(t==null?void 0:t.public).sort((n,r)=>{const o=n.split("/").filter(Boolean).length;return r.split("/").filter(Boolean).length-o}).find(n=>{var r;return window.location.pathname===n||(((r=e==null?void 0:e.match)==null?void 0:r.call(e,n))??window.location.pathname.startsWith(n))})??"/":(console.warn("No config found. Please call initializeConfig() first."),"/")}function h(){return l?Object.keys(l.public).filter(t=>t!=="default"&&t.startsWith("/")):(console.warn("No config found. Please call initializeConfig() first."),[])}function P(){return h().length>=1}function p(t){if(!i)throw new Error("Configuration not initialized. Call initializeConfig() first.");const e=i.headers??{};return{...e.all??{},...e[t]??{}}}function d(t,e){var n;const a=(n=t.public)==null?void 0:n.default;return e==="/"||!t.public[e]?a:s(a,t.public[e])}function v(t,e){return l=t,f=e??null,u=g(l,{match:e==null?void 0:e.match}),i=d(l,u),i}function S(t){if(!i)throw new Error("Configuration not initialized. Call initializeConfig() first.");return c(i,t)}export{S as getConfigValue,p as getHeaders,h as getListOfRootPaths,g as getRootPath,v as initializeConfig,P as isMultistore,z as resetConfig};
|
|
4
4
|
//# sourceMappingURL=configs.js.map
|
package/package.json
CHANGED