@descope-ui/descope-multi-line-mappings 3.11.8 → 3.12.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/package.json CHANGED
@@ -1,6 +1,10 @@
1
1
  {
2
2
  "name": "@descope-ui/descope-multi-line-mappings",
3
- "version": "3.11.8",
3
+ "version": "3.12.0",
4
+ "files": [
5
+ "src",
6
+ "stories"
7
+ ],
4
8
  "exports": {
5
9
  ".": {
6
10
  "import": "./src/component/index.js"
@@ -14,15 +18,15 @@
14
18
  },
15
19
  "devDependencies": {
16
20
  "@playwright/test": "1.58.2",
17
- "e2e-utils": "3.11.8",
18
- "test-drivers": "3.11.8"
21
+ "e2e-utils": "3.12.0",
22
+ "test-drivers": "3.12.0"
19
23
  },
20
24
  "dependencies": {
21
- "@descope-ui/common": "3.11.8",
22
- "@descope-ui/descope-button": "3.11.8",
23
- "@descope-ui/descope-multi-select-combo-box": "3.11.8",
24
- "@descope-ui/theme-globals": "3.11.8",
25
- "@descope-ui/theme-input-wrapper": "3.11.8"
25
+ "@descope-ui/common": "3.12.0",
26
+ "@descope-ui/descope-button": "3.12.0",
27
+ "@descope-ui/theme-input-wrapper": "3.12.0",
28
+ "@descope-ui/theme-globals": "3.12.0",
29
+ "@descope-ui/descope-multi-select-combo-box": "3.12.0"
26
30
  },
27
31
  "publishConfig": {
28
32
  "link-workspace-packages": false
package/.eslintrc.json DELETED
@@ -1,32 +0,0 @@
1
- {
2
- "extends": ["../../../../.eslintrc.json"],
3
- "ignorePatterns": ["!**/*"],
4
- "overrides": [
5
- {
6
- "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7
- "rules": {}
8
- },
9
- {
10
- "files": ["*.spec.ts", "*.spec.tsx"],
11
- "env": {
12
- "browser": true
13
- },
14
- "rules": {}
15
- },
16
- {
17
- "files": ["*.json"],
18
- "parser": "jsonc-eslint-parser",
19
- "rules": {
20
- "@nx/dependency-checks": [
21
- "error",
22
- {
23
- "ignoredFiles": [
24
- "{projectRoot}/eslint.config.{js,cjs,mjs}",
25
- "{projectRoot}/rollup.config.{js,ts,mjs,mts}"
26
- ]
27
- }
28
- ]
29
- }
30
- }
31
- ]
32
- }
package/CHANGELOG.md DELETED
@@ -1,48 +0,0 @@
1
- # Changelog
2
-
3
- This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
-
5
- ## [3.11.8](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.7...web-components-ui-3.11.8) (2026-05-25)
6
-
7
- ## [3.11.7](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.6...web-components-ui-3.11.7) (2026-05-25)
8
-
9
- ## [3.11.6](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.5...web-components-ui-3.11.6) (2026-05-24)
10
-
11
- ## [3.11.5](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.4...web-components-ui-3.11.5) (2026-05-21)
12
-
13
- ## [3.11.4](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.3...web-components-ui-3.11.4) (2026-05-20)
14
-
15
- ## [3.11.3](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.2...web-components-ui-3.11.3) (2026-05-19)
16
-
17
- ## [3.11.2](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.1...web-components-ui-3.11.2) (2026-05-19)
18
-
19
-
20
- ### Bug Fixes
21
-
22
- * **tooltip-wrapped:** sync stretch attr and hidden class for tooltip-wrapped components ([#1032](https://github.com/descope/web-components-ui/issues/1032)) ([669468f](https://github.com/descope/web-components-ui/commit/669468fd1cb8ff9a50b58e380a442c9c1e6e2b96))
23
-
24
- ## [3.11.1](https://github.com/descope/web-components-ui/compare/web-components-ui-3.11.0...web-components-ui-3.11.1) (2026-05-19)
25
-
26
-
27
- ### Bug Fixes
28
-
29
- * **multi-line-mappings:** stabilize e2e screenshot tests by waiting for combo visibility ([#1034](https://github.com/descope/web-components-ui/issues/1034)) ([1201d82](https://github.com/descope/web-components-ui/commit/1201d82107d990f143ac2c9d4a75964111317fe9))
30
-
31
- ## [3.11.0](https://github.com/descope/web-components-ui/compare/web-components-ui-3.10.2...web-components-ui-3.11.0) (2026-05-19)
32
-
33
- ## [3.10.2](https://github.com/descope/web-components-ui/compare/web-components-ui-3.10.1...web-components-ui-3.10.2) (2026-05-19)
34
-
35
- ## [3.10.1](https://github.com/descope/web-components-ui/compare/web-components-ui-3.10.0...web-components-ui-3.10.1) (2026-05-18)
36
-
37
- ## [3.10.0](https://github.com/descope/web-components-ui/compare/web-components-ui-3.9.2...web-components-ui-3.10.0) (2026-05-17)
38
-
39
- ## [3.9.2](https://github.com/descope/web-components-ui/compare/web-components-ui-3.9.1...web-components-ui-3.9.2) (2026-05-17)
40
-
41
- ## [3.9.1](https://github.com/descope/web-components-ui/compare/web-components-ui-3.9.0...web-components-ui-3.9.1) (2026-05-17)
42
-
43
- ## [3.9.0](https://github.com/descope/web-components-ui/compare/web-components-ui-3.8.0...web-components-ui-3.9.0) (2026-05-17)
44
-
45
-
46
- ### Features
47
-
48
- * added multi line mappings component ([#978](https://github.com/descope/web-components-ui/issues/978)) ([544552f](https://github.com/descope/web-components-ui/commit/544552f474430f7a9317e268979fb94694f6249a))
@@ -1,465 +0,0 @@
1
- import { expect, test } from '@playwright/test';
2
- import { createMultiLineMappingsTestDriver } from 'test-drivers';
3
- import { getStoryUrl, loopConfig, loopPresets } from 'e2e-utils';
4
-
5
- const storyName = 'descope-multi-line-mappings';
6
- const componentName = 'descope-multi-line-mappings';
7
-
8
- test.describe('theme', () => {
9
- test('default', async ({ page }) => {
10
- await page.goto(getStoryUrl(storyName, {}));
11
- await page.waitForSelector(componentName);
12
- await page.waitForTimeout(500);
13
- const component = createMultiLineMappingsTestDriver(
14
- page.locator(componentName),
15
- );
16
- expect(
17
- await component.screenshot({
18
- animations: 'disabled',
19
- timeout: 3000,
20
- caret: 'hide',
21
- }),
22
- ).toMatchSnapshot();
23
- });
24
-
25
- loopConfig(
26
- {
27
- size: ['xs', 'sm', 'lg'],
28
- 'full-width': ['true'],
29
- direction: ['rtl'],
30
- disabled: ['true'],
31
- readonly: ['true'],
32
- },
33
- (attr, value) => {
34
- test(`${attr}: ${value}`, async ({ page }) => {
35
- await page.goto(getStoryUrl(storyName, { [attr]: value }));
36
- await page.waitForSelector(componentName);
37
- await page.waitForTimeout(500);
38
- const component = createMultiLineMappingsTestDriver(
39
- page.locator(componentName),
40
- );
41
- expect(
42
- await component.screenshot({
43
- animations: 'disabled',
44
- timeout: 3000,
45
- caret: 'hide',
46
- }),
47
- ).toMatchSnapshot();
48
- });
49
- },
50
- );
51
-
52
- loopPresets(
53
- { 'with labels': { 'first-label': 'Source', 'second-label': 'Target' } },
54
- (preset, name) => {
55
- test(name, async ({ page }) => {
56
- await page.goto(getStoryUrl(storyName, preset));
57
- await page.waitForSelector(componentName);
58
- await page.waitForTimeout(500);
59
- const component = createMultiLineMappingsTestDriver(
60
- page.locator(componentName),
61
- );
62
- expect(
63
- await component.screenshot({
64
- animations: 'disabled',
65
- timeout: 3000,
66
- caret: 'hide',
67
- }),
68
- ).toMatchSnapshot();
69
- });
70
- },
71
- );
72
-
73
- test('with placeholders', async ({ page }) => {
74
- await page.goto(
75
- getStoryUrl(storyName, {
76
- 'first-placeholder': 'Select tenant',
77
- 'second-placeholder': 'Select role',
78
- }),
79
- );
80
- await page.waitForSelector(componentName);
81
- const component = createMultiLineMappingsTestDriver(
82
- page.locator(componentName),
83
- );
84
- await component.setValue([]);
85
- await page.waitForTimeout(500);
86
- expect(
87
- await component.screenshot({
88
- animations: 'disabled',
89
- timeout: 3000,
90
- caret: 'hide',
91
- }),
92
- ).toMatchSnapshot();
93
- });
94
-
95
- test('multiple rows', async ({ page }) => {
96
- await page.goto(getStoryUrl(storyName, {}));
97
- await page.waitForSelector(componentName);
98
- const component = createMultiLineMappingsTestDriver(
99
- page.locator(componentName),
100
- );
101
- await component.setValue([
102
- { firstValues: 'tenant-a', secondValues: ['viewer'] },
103
- { firstValues: 'tenant-b', secondValues: ['editor'] },
104
- ]);
105
- await page.waitForTimeout(500);
106
- expect(
107
- await component.screenshot({
108
- animations: 'disabled',
109
- timeout: 3000,
110
- caret: 'hide',
111
- }),
112
- ).toMatchSnapshot();
113
- });
114
- });
115
-
116
- test.describe('logic', () => {
117
- test('setting value updates combo selections', async ({ page }) => {
118
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
119
- await page.waitForTimeout(500);
120
-
121
- const component = createMultiLineMappingsTestDriver(
122
- page.locator(componentName),
123
- );
124
- const value = await component.getValue();
125
- expect(value).toStrictEqual([
126
- { firstValues: 'tenant-a', secondValues: ['viewer'] },
127
- ]);
128
- expect(
129
- await component.screenshot({ animations: 'disabled', caret: 'hide' }),
130
- ).toMatchSnapshot();
131
- });
132
-
133
- test.fixme('add row button adds a new empty row', async ({ page }) => {
134
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
135
- const component = createMultiLineMappingsTestDriver(
136
- page.locator(componentName),
137
- );
138
-
139
- await component.addButton.click();
140
-
141
- expect(await component.rows.count()).toBe(2);
142
- await component.getRow(1).firstCombo.locator.waitFor({ state: 'visible' });
143
- expect(
144
- await component.screenshot({ animations: 'disabled', caret: 'hide' }),
145
- ).toMatchSnapshot();
146
- });
147
-
148
- test('remove button removes the correct row', async ({ page }) => {
149
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
150
- const component = createMultiLineMappingsTestDriver(
151
- page.locator(componentName),
152
- );
153
- await component.setValue([
154
- { firstValues: 'tenant-a', secondValues: ['viewer'] },
155
- { firstValues: 'tenant-b', secondValues: ['editor'] },
156
- ]);
157
- await page.waitForTimeout(200);
158
-
159
- await component.getRow(0).removeButton.click();
160
-
161
- expect(await component.rows.count()).toBe(1);
162
- const value = await component.getValue();
163
- expect(value[0].firstValues).toBe('tenant-b');
164
- expect(
165
- await component.screenshot({ animations: 'disabled', caret: 'hide' }),
166
- ).toMatchSnapshot();
167
- });
168
-
169
- test('remove button is hidden when there is only one row', async ({
170
- page,
171
- }) => {
172
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
173
- const component = createMultiLineMappingsTestDriver(
174
- page.locator(componentName),
175
- );
176
-
177
- expect(await component.getRow(0).removeButton.isHidden()).toBe(true);
178
- expect(
179
- await component.screenshot({ animations: 'disabled', caret: 'hide' }),
180
- ).toMatchSnapshot();
181
- });
182
-
183
- test('add button is disabled when max rows is reached', async ({ browserName, page }) => {
184
- test.skip(browserName === 'webkit');
185
-
186
- await page.goto(getStoryUrl(storyName, { 'max-rows': '2' }), {
187
- waitUntil: 'networkidle',
188
- });
189
- const component = createMultiLineMappingsTestDriver(
190
- page.locator(componentName),
191
- );
192
-
193
- await component.addButton.click();
194
-
195
- expect(await component.rows.count()).toBe(2);
196
- expect(await component.addButton.getAttribute('disabled')).toBe('true');
197
- await component.getRow(1).firstCombo.locator.waitFor({ state: 'visible' });
198
- expect(
199
- await component.screenshot({ animations: 'disabled', caret: 'hide' }),
200
- ).toMatchSnapshot();
201
- });
202
-
203
- test('second combo options is intersection of all when no first value selected', async ({
204
- page,
205
- }) => {
206
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
207
- const component = createMultiLineMappingsTestDriver(
208
- page.locator(componentName),
209
- );
210
- await component.setValue([{ firstValues: '', secondValues: [] }]);
211
- await page.waitForTimeout(200);
212
-
213
- const { secondCombo } = component.getRow();
214
- await secondCombo.openDropdown();
215
- expect(await secondCombo.getItems()).toStrictEqual(['viewer']); // intersection of all tenants
216
- });
217
-
218
- test('selecting a first value filters second combo options', async ({
219
- page,
220
- }) => {
221
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
222
- const component = createMultiLineMappingsTestDriver(
223
- page.locator(componentName),
224
- );
225
- await component.setValue([{ firstValues: '', secondValues: [] }]);
226
- await page.waitForTimeout(200);
227
-
228
- const { firstCombo, secondCombo } = component.getRow();
229
-
230
- await firstCombo.openDropdown();
231
- await firstCombo.selectItem('tenant-a');
232
- await firstCombo.closeDropdown();
233
-
234
- await secondCombo.openDropdown();
235
- expect(await secondCombo.getItems()).toStrictEqual([
236
- 'viewer',
237
- 'editor',
238
- 'admin',
239
- ]);
240
-
241
- expect(
242
- await component.screenshot({ animations: 'disabled', caret: 'hide' }),
243
- ).toMatchSnapshot();
244
- });
245
-
246
- test('selecting multiple first values shows intersection in second combo options', async ({
247
- page,
248
- }) => {
249
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
250
- const component = createMultiLineMappingsTestDriver(
251
- page.locator(componentName),
252
- );
253
- await component.setValue([{ firstValues: '', secondValues: [] }]);
254
- await page.waitForTimeout(200);
255
-
256
- const { firstCombo, secondCombo } = component.getRow();
257
-
258
- await firstCombo.openDropdown();
259
- await firstCombo.selectItem('tenant-a'); // viewer, editor, admin
260
- await firstCombo.selectItem('tenant-b'); // viewer, editor
261
- await firstCombo.closeDropdown();
262
-
263
- await secondCombo.openDropdown();
264
- expect(await secondCombo.getItems()).toStrictEqual(['viewer', 'editor']); // intersection
265
- });
266
-
267
- test('selecting a role unique to a tenant, adding another tenant removes it, removing the tenant restores it', async ({
268
- page,
269
- }) => {
270
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
271
- const component = createMultiLineMappingsTestDriver(
272
- page.locator(componentName),
273
- );
274
- await component.setValue([{ firstValues: '', secondValues: [] }]);
275
- await page.waitForTimeout(200);
276
-
277
- const { firstCombo, secondCombo } = component.getRow();
278
-
279
- // Select tenant-c which has the unique role: auditor
280
- await firstCombo.openDropdown();
281
- await firstCombo.selectItem('tenant-c');
282
- await firstCombo.closeDropdown();
283
-
284
- // Select auditor
285
- await secondCombo.openDropdown();
286
- await secondCombo.selectItem('auditor');
287
- await secondCombo.closeDropdown();
288
- expect(await component.getValue()).toStrictEqual([
289
- { firstValues: 'tenant-c', secondValues: ['auditor'] },
290
- ]);
291
-
292
- // Add tenant-b — auditor is not in its options, so it is dropped from second selection
293
- await firstCombo.openDropdown();
294
- await firstCombo.selectItem('tenant-b');
295
- await firstCombo.closeDropdown();
296
- await page.waitForTimeout(100);
297
-
298
- expect(await component.getValue()).toStrictEqual([
299
- { firstValues: 'tenant-c', secondValues: [] },
300
- { firstValues: 'tenant-b', secondValues: [] },
301
- ]);
302
- expect(
303
- await component.screenshot({ animations: 'disabled', caret: 'hide' }),
304
- ).toMatchSnapshot();
305
-
306
- // Remove tenant-b — auditor should be available again
307
- await firstCombo.openDropdown();
308
- await firstCombo.selectItem('tenant-b'); // deselect
309
- await firstCombo.closeDropdown();
310
- await page.waitForTimeout(100);
311
-
312
- await secondCombo.openDropdown();
313
- expect(await secondCombo.getItems()).toContain('auditor');
314
-
315
- await secondCombo.selectItem('auditor');
316
- await secondCombo.closeDropdown();
317
- expect(await component.getValue()).toStrictEqual([
318
- { firstValues: 'tenant-c', secondValues: ['auditor'] },
319
- ]);
320
- expect(
321
- await component.screenshot({ animations: 'disabled', caret: 'hide' }),
322
- ).toMatchSnapshot();
323
- });
324
-
325
- test('custom value keys are used in component value', async ({ page }) => {
326
- await page.goto(
327
- getStoryUrl(storyName, {
328
- 'first-value-key': 'tenants',
329
- 'second-value-key': 'roles',
330
- }),
331
- { waitUntil: 'networkidle' },
332
- );
333
- const component = createMultiLineMappingsTestDriver(
334
- page.locator(componentName),
335
- );
336
- await component.setValue([{ tenants: '', roles: [] }]);
337
- await page.waitForTimeout(200);
338
-
339
- const { firstCombo, secondCombo } = component.getRow();
340
-
341
- await firstCombo.openDropdown();
342
- await firstCombo.selectItem('tenant-a');
343
- await firstCombo.closeDropdown();
344
- await secondCombo.openDropdown();
345
- await secondCombo.selectItem('viewer');
346
-
347
- expect(await component.getValue()).toStrictEqual([
348
- { tenants: 'tenant-a', roles: ['viewer'] },
349
- ]);
350
- });
351
-
352
- test('dispatches input event when value changes', async ({ page }) => {
353
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
354
- const component = createMultiLineMappingsTestDriver(
355
- page.locator(componentName),
356
- );
357
- await component.setValue([{ firstValues: '', secondValues: [] }]);
358
-
359
- await page.evaluate((name) => {
360
- (window as any).__inputFired = false;
361
- document.querySelector(name)!.addEventListener('input', () => {
362
- (window as any).__inputFired = true;
363
- });
364
- }, componentName);
365
-
366
- const { firstCombo } = component.getRow();
367
- await firstCombo.openDropdown();
368
- await firstCombo.selectItem('tenant-a');
369
-
370
- expect(await page.evaluate(() => (window as any).__inputFired)).toBe(true);
371
- });
372
-
373
- test('empty rows are omitted from value', async ({ page }) => {
374
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
375
- const component = createMultiLineMappingsTestDriver(
376
- page.locator(componentName),
377
- );
378
-
379
- await component.setValue([{ firstValues: '', secondValues: [] }]);
380
-
381
- expect(await component.getValue()).toStrictEqual([]);
382
- });
383
-
384
- test('only non-empty rows are included in value', async ({ page }) => {
385
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
386
- const component = createMultiLineMappingsTestDriver(
387
- page.locator(componentName),
388
- );
389
-
390
- await component.setValue([
391
- { firstValues: 'tenant-a', secondValues: ['viewer'] },
392
- { firstValues: '', secondValues: [] },
393
- ]);
394
- await page.waitForTimeout(200);
395
-
396
- expect(await component.getValue()).toStrictEqual([
397
- { firstValues: 'tenant-a', secondValues: ['viewer'] },
398
- ]);
399
- });
400
-
401
- test('adding a row does not fire an input event', async ({ page }) => {
402
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
403
- const component = createMultiLineMappingsTestDriver(
404
- page.locator(componentName),
405
- );
406
-
407
- await page.evaluate((name) => {
408
- (window as any).__inputFired = false;
409
- document.querySelector(name)!.addEventListener('input', () => {
410
- (window as any).__inputFired = true;
411
- });
412
- }, componentName);
413
-
414
- await component.addButton.click();
415
-
416
- expect(await page.evaluate(() => (window as any).__inputFired)).toBe(false);
417
- });
418
-
419
- test('removing an empty row does not fire an input event', async ({
420
- page,
421
- }) => {
422
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
423
- const component = createMultiLineMappingsTestDriver(
424
- page.locator(componentName),
425
- );
426
-
427
- await component.setValue([{ firstValues: '', secondValues: [] }]);
428
- await component.addButton.click();
429
-
430
- await page.evaluate((name) => {
431
- (window as any).__inputFired = false;
432
- document.querySelector(name)!.addEventListener('input', () => {
433
- (window as any).__inputFired = true;
434
- });
435
- }, componentName);
436
-
437
- await component.getRow(0).removeButton.click();
438
-
439
- expect(await page.evaluate(() => (window as any).__inputFired)).toBe(false);
440
- });
441
-
442
- test('removing a non-empty row fires an input event', async ({ page }) => {
443
- await page.goto(getStoryUrl(storyName, {}), { waitUntil: 'networkidle' });
444
- const component = createMultiLineMappingsTestDriver(
445
- page.locator(componentName),
446
- );
447
-
448
- await component.setValue([
449
- { firstValues: 'tenant-a', secondValues: ['viewer'] },
450
- { firstValues: 'tenant-b', secondValues: ['editor'] },
451
- ]);
452
- await page.waitForTimeout(200);
453
-
454
- await page.evaluate((name) => {
455
- (window as any).__inputFired = false;
456
- document.querySelector(name)!.addEventListener('input', () => {
457
- (window as any).__inputFired = true;
458
- });
459
- }, componentName);
460
-
461
- await component.getRow(0).removeButton.click();
462
-
463
- expect(await page.evaluate(() => (window as any).__inputFired)).toBe(true);
464
- });
465
- });
package/project.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "name": "@descope-ui/descope-multi-line-mappings",
3
- "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
- "sourceRoot": "packages/web-components/components/descope-multi-line-mappings/src",
5
- "projectType": "library",
6
- "targets": {},
7
- "tags": []
8
- }