tosijs-ui 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +4 -2
  2. package/dist/iife.js +70 -60
  3. package/dist/iife.js.map +42 -42
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +15 -37
  6. package/dist/index.js.map +39 -39
  7. package/dist/version.d.ts +1 -1
  8. package/package.json +2 -2
  9. package/dist/ab-test.js +0 -116
  10. package/dist/babylon-3d.js +0 -292
  11. package/dist/bodymovin-player.js +0 -172
  12. package/dist/bp-loader.js +0 -26
  13. package/dist/carousel.js +0 -308
  14. package/dist/code-editor.js +0 -102
  15. package/dist/color-input.js +0 -112
  16. package/dist/data-table.js +0 -774
  17. package/dist/drag-and-drop.js +0 -386
  18. package/dist/editable-rect.js +0 -450
  19. package/dist/filter-builder.js +0 -468
  20. package/dist/float.js +0 -170
  21. package/dist/form.js +0 -466
  22. package/dist/gamepad.js +0 -115
  23. package/dist/icon-data.js +0 -308
  24. package/dist/icon-types.js +0 -1
  25. package/dist/icons.js +0 -374
  26. package/dist/index-iife.js +0 -4
  27. package/dist/live-example.js +0 -611
  28. package/dist/localize.js +0 -381
  29. package/dist/make-sorter.js +0 -119
  30. package/dist/make-sorter.test.d.ts +0 -1
  31. package/dist/make-sorter.test.js +0 -48
  32. package/dist/mapbox.js +0 -161
  33. package/dist/markdown-viewer.js +0 -173
  34. package/dist/match-shortcut.js +0 -13
  35. package/dist/match-shortcut.test.d.ts +0 -1
  36. package/dist/match-shortcut.test.js +0 -194
  37. package/dist/menu.js +0 -614
  38. package/dist/notifications.js +0 -308
  39. package/dist/password-strength.js +0 -302
  40. package/dist/playwright.config.d.ts +0 -9
  41. package/dist/playwright.config.js +0 -73
  42. package/dist/pop-float.js +0 -231
  43. package/dist/rating.js +0 -192
  44. package/dist/rich-text.js +0 -296
  45. package/dist/segmented.js +0 -298
  46. package/dist/select.js +0 -427
  47. package/dist/side-nav.js +0 -106
  48. package/dist/size-break.js +0 -118
  49. package/dist/sizer.js +0 -92
  50. package/dist/src/ab-test.d.ts +0 -14
  51. package/dist/src/babylon-3d.d.ts +0 -53
  52. package/dist/src/bodymovin-player.d.ts +0 -32
  53. package/dist/src/bp-loader.d.ts +0 -0
  54. package/dist/src/carousel.d.ts +0 -113
  55. package/dist/src/code-editor.d.ts +0 -27
  56. package/dist/src/color-input.d.ts +0 -41
  57. package/dist/src/data-table.d.ts +0 -79
  58. package/dist/src/drag-and-drop.d.ts +0 -2
  59. package/dist/src/editable-rect.d.ts +0 -97
  60. package/dist/src/filter-builder.d.ts +0 -64
  61. package/dist/src/float.d.ts +0 -18
  62. package/dist/src/form.d.ts +0 -68
  63. package/dist/src/gamepad.d.ts +0 -34
  64. package/dist/src/icon-data.d.ts +0 -309
  65. package/dist/src/icon-types.d.ts +0 -7
  66. package/dist/src/icons.d.ts +0 -17
  67. package/dist/src/index.d.ts +0 -37
  68. package/dist/src/live-example.d.ts +0 -51
  69. package/dist/src/localize.d.ts +0 -30
  70. package/dist/src/make-sorter.d.ts +0 -3
  71. package/dist/src/mapbox.d.ts +0 -24
  72. package/dist/src/markdown-viewer.d.ts +0 -15
  73. package/dist/src/match-shortcut.d.ts +0 -9
  74. package/dist/src/menu.d.ts +0 -60
  75. package/dist/src/notifications.d.ts +0 -106
  76. package/dist/src/password-strength.d.ts +0 -35
  77. package/dist/src/pop-float.d.ts +0 -10
  78. package/dist/src/rating.d.ts +0 -62
  79. package/dist/src/rich-text.d.ts +0 -28
  80. package/dist/src/segmented.d.ts +0 -80
  81. package/dist/src/select.d.ts +0 -43
  82. package/dist/src/side-nav.d.ts +0 -36
  83. package/dist/src/size-break.d.ts +0 -18
  84. package/dist/src/sizer.d.ts +0 -34
  85. package/dist/src/tab-selector.d.ts +0 -91
  86. package/dist/src/tag-list.d.ts +0 -37
  87. package/dist/src/track-drag.d.ts +0 -5
  88. package/dist/src/version.d.ts +0 -1
  89. package/dist/src/via-tag.d.ts +0 -2
  90. package/dist/tab-selector.js +0 -326
  91. package/dist/tag-list.js +0 -375
  92. package/dist/track-drag.js +0 -143
  93. package/dist/version.js +0 -1
  94. package/dist/via-tag.js +0 -102
@@ -1,308 +0,0 @@
1
- /*#
2
-
3
- # notifications
4
-
5
- `XinNotification` provides a singleton custom `<xin-notification>` element that manages
6
- a list of notifications.
7
-
8
- The notifications are displayed most-recent first. If the notifications would take more than
9
- half the height of the display, they are scrolled.
10
-
11
- You can post a notification simply with `XinNotification.post()` or `postNotification()`.
12
-
13
- ```
14
- interface NotificationSpec {
15
- message: string
16
- type?: 'success' | 'info' | 'log' | 'warn' | 'error' | 'progress' // default 'info'
17
- icon?: SVGElement | string // defaults to an info icon
18
- duration?: number
19
- progress?: () => number // return percentage completion
20
- close?: () => void
21
- }
22
- ```
23
-
24
- If you provide a `progress` callback (which is assumed to return a number from `0-100`, with
25
- 100+ indicating completion) then `XinNotification` will poll it every second until the
26
- task completes or the notification is closed. Returning 100 or more will automatically close
27
- the notification.
28
-
29
- If you configure a notification's `type = "progress"` but don't provide a `progress` callback
30
- then an indefinite `<progress>` element will be displayed.
31
-
32
- If you provide a `close` callback, it will be fired if the user closes the notification.
33
-
34
- `postNotification` returns a callback function that closes the note programmatically (e.g.
35
- when an operation completes). This will *also* call any `close` callback function you
36
- provided. (The progress demos in the example exercise this functionality.)
37
-
38
- ```js
39
- const { postNotification, icons } = xinjsui
40
-
41
- const form = preview.querySelector('xin-form')
42
- const submit = preview.querySelector('.submit')
43
- const closeButton = preview.querySelector('.close')
44
-
45
- let close
46
-
47
- form.submitCallback = (value, isValid) => {
48
- if (!isValid) return
49
- if (value.type.startsWith('progress')) {
50
- startTime = Date.now()
51
- const { message, duration, icon } = value
52
- close = postNotification({
53
- message,
54
- type: 'progress',
55
- icon,
56
- progress: value.type === 'progress' ? () => (Date.now() - startTime) / (10 * duration) : undefined,
57
- close: () => { postNotification(`${value.message} cancelled`) },
58
- })
59
- } else {
60
- close = postNotification(value)
61
- }
62
- console.log(close)
63
- closeButton.disabled = false
64
- }
65
-
66
- submit.addEventListener('click', form.submit)
67
- closeButton.addEventListener('click', () => {
68
- if (close) {
69
- close()
70
- }
71
- })
72
-
73
- postNotification({
74
- message: 'Welcome to xinjs-ui notifications, this message will disappear in 2s',
75
- duration: 2
76
- })
77
- ```
78
- ```html
79
- <xin-form>
80
- <h3 slot="header">Notification Test</h3>
81
- <xin-field caption="Message" key="message" type="string" value="This is a test…"></xin-field>
82
- <xin-field caption="Type" key="type" value="info">
83
- <xin-select slot="input"
84
- options="error,warn,info,success,log,,progress,progress (indefinite)"
85
- ></xin-select>
86
- </xin-field>
87
- <xin-field caption="Icon" key="icon" value="info">
88
- <xin-select slot="input"
89
- options="info,bug,thumbsUp,thumbsDown,message"
90
- ></xin-select>
91
- </xin-field>
92
- <xin-field caption="Duration" key="duration" type="number" value="2"></xin-field>
93
- <button slot="footer" class="close" disabled>Close Last Notification</button>
94
- <span slot="footer" class="elastic"></span>
95
- <button slot="footer" class="submit">Post Notification</button>
96
- </xin-form>
97
- ```
98
- ```css
99
- xin-form {
100
- height: 100%;
101
- }
102
-
103
- xin-form::part(content) {
104
- display: flex;
105
- flex-direction: column;
106
- padding: 10px;
107
- gap: 10px;
108
- background: var(--background);
109
- }
110
-
111
- xin-form::part(header),
112
- xin-form::part(footer) {
113
- background: #eee;
114
- justify-content: center;
115
- padding: 10px;
116
- }
117
-
118
- xin-form h3 {
119
- margin: 0;
120
- }
121
-
122
- xin-form label {
123
- display: grid;
124
- grid-template-columns: 120px 1fr;
125
- }
126
- ```
127
-
128
- ## `postNotification(spec: NotificationSpec | string)`
129
-
130
- This is simply a wrapper for `XinNotification.post()`.
131
- */
132
- import { Component, elements, vars } from 'xinjs';
133
- import { icons } from './icons';
134
- import { findHighestZ } from './track-drag';
135
- const { div, button } = elements;
136
- const COLOR_MAP = {
137
- error: 'red',
138
- warn: 'orange',
139
- info: 'royalblue',
140
- log: 'gray',
141
- success: 'green',
142
- progress: 'royalblue',
143
- };
144
- export class XinNotification extends Component {
145
- static singleton;
146
- static styleSpec = {
147
- ':host': {
148
- _notificationSpacing: 8,
149
- _notificationWidth: 360,
150
- _notificationPadding: `${vars.notificationSpacing} ${vars.notificationSpacing50} ${vars.notificationSpacing} ${vars.notificationSpacing200}`,
151
- _notificationBg: '#fafafa',
152
- _notificationAccentColor: '#aaa',
153
- _notificationTextColor: '#444',
154
- _notificationIconSize: vars.notificationSpacing300,
155
- _notificationButtonSize: 48,
156
- _notificationBorderWidth: '3px 0 0',
157
- _notificationBorderRadius: vars.notificationSpacing50,
158
- position: 'fixed',
159
- left: 0,
160
- right: 0,
161
- bottom: 0,
162
- paddingBottom: vars.notificationSpacing,
163
- width: vars.notificationWidth,
164
- display: 'flex',
165
- flexDirection: 'column-reverse',
166
- margin: '0 auto',
167
- gap: vars.notificationSpacing,
168
- maxHeight: '50vh',
169
- overflow: 'hidden auto',
170
- boxShadow: 'none !important',
171
- },
172
- ':host *': {
173
- color: vars.notificationTextColor,
174
- },
175
- ':host .note': {
176
- display: 'grid',
177
- background: vars.notificationBg,
178
- padding: vars.notificationPadding,
179
- gridTemplateColumns: `${vars.notificationIconSize} 1fr ${vars.notificationButtonSize}`,
180
- gap: vars.notificationSpacing,
181
- alignItems: 'center',
182
- borderRadius: vars.notificationBorderRadius,
183
- boxShadow: `0 2px 8px #0006, inset 0 0 0 2px ${vars.notificationAccentColor}`,
184
- borderColor: vars.notificationAccentColor,
185
- borderWidth: vars.notificationBorderWidth,
186
- borderStyle: 'solid',
187
- transition: '0.5s ease-in',
188
- transitionProperty: 'margin, opacity',
189
- zIndex: 1,
190
- },
191
- ':host .note .icon': {
192
- stroke: vars.notificationAccentColor,
193
- },
194
- ':host .note button': {
195
- display: 'flex',
196
- lineHeight: vars.notificationButtonSize,
197
- padding: 0,
198
- margin: 0,
199
- height: vars.notificationButtonSize,
200
- width: vars.notificationButtonSize,
201
- background: 'transparent',
202
- alignItems: 'center',
203
- justifyContent: 'center',
204
- boxShadow: 'none',
205
- border: 'none',
206
- position: 'relative',
207
- },
208
- ':host .note button:hover svg': {
209
- stroke: vars.notificationAccentColor,
210
- },
211
- ':host .note button:active svg': {
212
- borderRadius: 99,
213
- stroke: vars.notificationBg,
214
- background: vars.notificationAccentColor,
215
- padding: vars.spacing50,
216
- },
217
- ':host .note svg': {
218
- height: vars.notificationIconSize,
219
- width: vars.notificationIconSize,
220
- pointerEvents: 'none',
221
- },
222
- ':host .message': {
223
- display: 'flex',
224
- flexDirection: 'column',
225
- alignItems: 'center',
226
- gap: vars.notificationSpacing,
227
- },
228
- ':host .note.closing': {
229
- opacity: 0,
230
- zIndex: 0,
231
- },
232
- };
233
- static removeNote(note) {
234
- note.classList.add('closing');
235
- note.style.marginBottom = -note.offsetHeight + 'px';
236
- const remove = () => {
237
- note.remove();
238
- };
239
- note.addEventListener('transitionend', remove);
240
- setTimeout(remove, 1000);
241
- }
242
- static post(spec) {
243
- const { message, duration, type, close, progress, icon } = Object.assign({ type: 'info', duration: -1 }, typeof spec === 'string' ? { message: spec } : spec);
244
- if (!this.singleton) {
245
- this.singleton = xinNotification();
246
- }
247
- const singleton = this.singleton;
248
- document.body.append(singleton);
249
- singleton.style.zIndex = String(findHighestZ() + 1);
250
- const _notificationAccentColor = COLOR_MAP[type];
251
- const progressBar = progress || type === 'progress' ? elements.progress() : {};
252
- const closeCallback = () => {
253
- if (close) {
254
- close();
255
- }
256
- XinNotification.removeNote(note);
257
- };
258
- const iconElement = icon instanceof SVGElement
259
- ? icon
260
- : icon
261
- ? icons[icon]({ class: 'icon' })
262
- : icons.info({ class: 'icon' });
263
- const note = div({
264
- class: `note ${type}`,
265
- style: {
266
- _notificationAccentColor,
267
- },
268
- }, iconElement, div({ class: 'message' }, div(message), progressBar), button({
269
- class: 'close',
270
- title: 'close',
271
- // we can't use onClick because this lives inside a shadowDOM
272
- apply(elt) {
273
- elt.addEventListener('click', closeCallback);
274
- },
275
- }, icons.x()));
276
- singleton.shadowRoot.append(note);
277
- if (progressBar instanceof HTMLProgressElement &&
278
- progress instanceof Function) {
279
- progressBar.setAttribute('max', String(100));
280
- progressBar.value = progress();
281
- const interval = setInterval(() => {
282
- if (!singleton.shadowRoot.contains(note)) {
283
- clearInterval(interval);
284
- return;
285
- }
286
- const percentage = progress();
287
- progressBar.value = percentage;
288
- if (percentage >= 100) {
289
- XinNotification.removeNote(note);
290
- }
291
- }, 1000);
292
- }
293
- if (duration > 0) {
294
- setTimeout(() => {
295
- XinNotification.removeNote(note);
296
- }, duration * 1000);
297
- }
298
- note.scrollIntoView();
299
- return closeCallback;
300
- }
301
- content = null;
302
- }
303
- export const xinNotification = XinNotification.elementCreator({
304
- tag: 'xin-notification',
305
- });
306
- export function postNotification(spec) {
307
- return XinNotification.post(spec);
308
- }
@@ -1,302 +0,0 @@
1
- /*#
2
- # password strength
3
-
4
- Just wrap it a `<xin-password-strength>` element around an `<input>`
5
- and it will gauge its content strength as a password. It will also
6
- let you **securely verify** that the password hasn't been breached.
7
-
8
- ```js
9
- const { xinLocalized, localize } = xinjsui
10
-
11
- const toggle = preview.querySelector('.toggle')
12
- const icon = preview.querySelector('xin-icon')
13
- const input = preview.querySelector('input')
14
- const breach = preview.querySelector('.breach')
15
- const output = preview.querySelector('.output')
16
- const passwordStrength = preview.querySelector('xin-password-strength')
17
-
18
- // Localization Example
19
- passwordStrength.append(xinLocalized({
20
- refString: 'Yes',
21
- localeChanged () {
22
- this.parentElement.strengthDescriptions = [
23
- 'unacceptable',
24
- 'very weak',
25
- 'weak',
26
- 'moderate',
27
- 'strong',
28
- 'very strong',
29
- ].map(localize)
30
- this.parentElement.queueRender()
31
- }
32
- }))
33
-
34
- toggle.addEventListener('click', () => {
35
- if (icon.icon === 'eye') {
36
- input.type = 'text'
37
- icon.icon = 'eyeOff'
38
- } else {
39
- input.type = 'password'
40
- icon.icon = 'eye'
41
- }
42
- })
43
-
44
- breach.addEventListener('click', async () => {
45
- preview.querySelector('xin-password-strength').isBreached().then(isBreached => {
46
- output.textContent =
47
- isBreached
48
- ? 'This password has been breached, look at console for details'
49
- : 'Seems OK'
50
- output.classList.toggle('breached', isBreached)
51
- })
52
- })
53
- ```
54
- ```html
55
- <xin-password-strength>
56
- <input class="password" type="password">
57
- <button class="toggle">
58
- <xin-icon icon="eye"></xin-icon>
59
- </button>
60
- </xin-password-strength>
61
-
62
- <br><br>
63
- <button class="breach">
64
- <xin-localized>Check if breached</xin-localized>
65
- </button>
66
- <div class="output"></div>
67
- ```
68
- ```css
69
- input.password {
70
- box-shadow: inset 0 0 0 2px var(--indicator-color);
71
- }
72
-
73
- .breached {
74
- color: white;
75
- background: red;
76
- }
77
- ```
78
-
79
- ## Algorithm
80
-
81
- The password is assessed to have a strength based on:
82
-
83
- - **length** one point for at least `goodLength` characters long.
84
- - **[a-z]** one point for containing a lowercase letter
85
- - **[A-Z]** one point for containing an uppercase letter
86
- - **[0-9]** one point for containing a numeric character
87
- - **^[a-zA-Z0-9]]** one point for containing some other kind of character
88
-
89
- A password smaller than `minLength` is an automatic `0`.
90
-
91
- ## Attributes
92
-
93
- - `minLength` defaults to `8`
94
- - `goodLength` defaults to `12`
95
- - `indicatorColors` six HTML colors, separated by commas, defaults to `'#f00,#f40,#f80,#ef0,#8f0,#0d4'`
96
- - `descriptionColors` six HTML colors, sepeated by commans, defaults to `'#000,#000,#000,#000,#000,#fff'`
97
-
98
- ## Properties
99
-
100
- - `value`, `strength` is a number from 0 to 5
101
- - `issues` is a structure which you can use to generate feedback
102
-
103
- ```
104
- <xin-password-strength>.issues = {
105
- tooShort: boolean,
106
- short: boolean,
107
- noUpper: boolean,
108
- noLower: boolean,
109
- noNumber: boolean,
110
- noSpecial: boolean,
111
- }
112
- ```
113
-
114
- ## Customizing / Localizing Strings
115
-
116
- The following properties control the feedback generated.
117
-
118
- ```
119
- issueDescriptions = {
120
- tooShort: 'too short',
121
- short: 'short',
122
- noUpper: 'no upper case',
123
- noLower: 'no lower case',
124
- noNumber: 'no digits',
125
- noSpecial: 'no unusual characters',
126
- }
127
- ```
128
-
129
- ```
130
- strengthDescriptions = [
131
- 'unacceptable',
132
- 'very weak',
133
- 'weak',
134
- 'moderate',
135
- 'strong',
136
- 'very strong',
137
- ]
138
- ```
139
-
140
- ## `isBreached()`
141
-
142
- `<xin-password-meter>` also provides an `isBreached(): Promise<boolean>` method
143
- which uses [weakpass.com's API](https://weakpass.com/) to tell you if the password has been
144
- breached.
145
-
146
- > Note that `isBreached` does not send the plain-text password anywhere. It uses **SHA-1**
147
- to hash the password and then sends that for lookup.
148
-
149
- ## Utility Functions
150
-
151
- Two functions used internally for querying [Weakpass,com](https://weakpass.com/) are
152
- provided in case they're useful on their own.
153
-
154
- `isBreached(password: striing): Promise<boolean>` will return `true` if the password is
155
- found in Weakpass's database (and spit out extra info to the console).
156
-
157
- `digest(s: string, method="sha-1"): Promise<string>` is just a nice wrapper for `crypto.digest`.
158
- */
159
- import { Component, elements, vars, varDefault } from 'xinjs';
160
- export const digest = async (s, method = 'SHA-1') => {
161
- // Convert password to an ArrayBuffer
162
- const encoder = new TextEncoder();
163
- const data = encoder.encode(s);
164
- // Hash the password using SHA-1
165
- const hashBuffer = await crypto.subtle.digest(method, data);
166
- // Convert the hash to a hexadecimal string
167
- const hashArray = Array.from(new Uint8Array(hashBuffer));
168
- const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
169
- return hashHex;
170
- };
171
- export const isBreached = async (password) => {
172
- const hashHex = await digest(password);
173
- const response = await fetch(`https://weakpass.com/api/v1/search/${hashHex}`);
174
- if (response.ok) {
175
- const result = await response.json();
176
- console.log('password found in weakpass database', result);
177
- }
178
- return response.status !== 404;
179
- };
180
- const { span, xinSlot } = elements;
181
- export class XinPasswordStrength extends Component {
182
- minLength = 8;
183
- goodLength = 12;
184
- indicatorColors = '#f00,#f40,#f80,#ef0,#8f0,#0a2';
185
- descriptionColors = '#000,#000,#000,#000,#000,#fff';
186
- issues = {
187
- tooShort: true,
188
- short: true,
189
- noUpper: true,
190
- noLower: true,
191
- noNumber: true,
192
- noSpecial: true,
193
- };
194
- issueDescriptions = {
195
- tooShort: 'too short',
196
- short: 'short',
197
- noUpper: 'no upper case',
198
- noLower: 'no lower case',
199
- noNumber: 'no digits',
200
- noSpecial: 'no unusual characters',
201
- };
202
- value = 0;
203
- strengthDescriptions = [
204
- 'unacceptable',
205
- 'very weak',
206
- 'weak',
207
- 'moderate',
208
- 'strong',
209
- 'very strong',
210
- ];
211
- constructor() {
212
- super();
213
- this.initAttributes('minLength', 'goodLength', 'indicatorColors');
214
- }
215
- strength(password) {
216
- this.issues = {
217
- tooShort: password.length < this.minLength,
218
- short: password.length < this.goodLength,
219
- noUpper: !password.match(/[A-Z]/),
220
- noLower: !password.match(/[a-z]/),
221
- noNumber: !password.match(/[0-9]/),
222
- noSpecial: !password.match(/[^a-zA-Z0-9]/),
223
- };
224
- return this.issues.tooShort
225
- ? 0
226
- : Object.values(this.issues).filter((v) => !v).length - 1;
227
- }
228
- async isBreached() {
229
- const password = this.querySelector('input')?.value;
230
- if (!password || typeof password !== 'string') {
231
- return true;
232
- }
233
- return await isBreached(password);
234
- }
235
- updateIndicator = (password) => {
236
- const { level, description } = this.parts;
237
- const colors = this.indicatorColors.split(',');
238
- const descriptionColors = this.descriptionColors.split(',');
239
- const strength = this.strength(password);
240
- if (this.value !== strength) {
241
- this.value = strength;
242
- this.dispatchEvent(new Event('change'));
243
- }
244
- level.style.width = `${(strength + 1) * 16.67}%`;
245
- this.style.setProperty('--indicator-color', colors[strength]);
246
- this.style.setProperty('--description-color', descriptionColors[strength]);
247
- description.textContent = this.strengthDescriptions[strength];
248
- };
249
- update = (event) => {
250
- const input = event.target.closest('input');
251
- this.updateIndicator(input?.value || '');
252
- };
253
- content = () => [
254
- xinSlot({ onInput: this.update }),
255
- span({ part: 'meter' }, span({ part: 'level' }), span({ part: 'description' })),
256
- ];
257
- render() {
258
- super.render();
259
- const input = this.querySelector('input');
260
- this.updateIndicator(input?.value);
261
- }
262
- }
263
- export const xinPasswordStrength = XinPasswordStrength.elementCreator({
264
- tag: 'xin-password-strength',
265
- styleSpec: {
266
- ':host': {
267
- display: 'inline-flex',
268
- flexDirection: 'column',
269
- gap: vars.spacing50,
270
- position: 'relative',
271
- },
272
- ':host xin-slot': {
273
- display: 'flex',
274
- },
275
- ':host [part="meter"]': {
276
- display: 'block',
277
- position: 'relative',
278
- height: varDefault.meterHeight('24px'),
279
- background: varDefault.indicatorBg('white'),
280
- borderRadius: varDefault.meterRadius('4px'),
281
- boxShadow: varDefault.meterShadow(`inset 0 0 0 2px ${vars.indicatorColor}`),
282
- },
283
- ':host [part="level"]': {
284
- height: varDefault.levelHeight('20px'),
285
- content: '" "',
286
- display: 'inline-block',
287
- width: 0,
288
- transition: '0.15s ease-out',
289
- background: vars.indicatorColor,
290
- margin: varDefault.levelMargin('2px'),
291
- borderRadius: varDefault.levelRadius('2px'),
292
- },
293
- ':host [part="description"]': {
294
- position: 'absolute',
295
- inset: '0',
296
- color: vars.descriptionColor,
297
- height: varDefault.meterHeight('24px'),
298
- lineHeight: varDefault.meterHeight('24px'),
299
- textAlign: 'center',
300
- },
301
- },
302
- });
@@ -1,9 +0,0 @@
1
- /**
2
- * Read environment variables from file.
3
- * https://github.com/motdotla/dotenv
4
- */
5
- /**
6
- * See https://playwright.dev/docs/test-configuration.
7
- */
8
- declare const _default: import("@playwright/test").PlaywrightTestConfig<{}, {}>;
9
- export default _default;
@@ -1,73 +0,0 @@
1
- import { defineConfig, devices } from '@playwright/test';
2
- /**
3
- * Read environment variables from file.
4
- * https://github.com/motdotla/dotenv
5
- */
6
- // import dotenv from 'dotenv';
7
- // dotenv.config({ path: path.resolve(__dirname, '.env') });
8
- /**
9
- * See https://playwright.dev/docs/test-configuration.
10
- */
11
- export default defineConfig({
12
- testDir: './tests',
13
- /* Run tests in files in parallel */
14
- fullyParallel: true,
15
- /* Fail the build on CI if you accidentally left test.only in the source code. */
16
- forbidOnly: !!process.env.CI,
17
- /* Retry on CI only */
18
- retries: process.env.CI ? 2 : 0,
19
- /* Opt out of parallel tests on CI. */
20
- workers: process.env.CI ? 1 : undefined,
21
- /* Reporter to use. See https://playwright.dev/docs/test-reporters */
22
- reporter: 'html',
23
- /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
24
- /* use .pw.ts for playwright (vs. bun) tests */
25
- testMatch: /.*\.pw\.ts/,
26
- use: {
27
- /* Base URL to use in actions like `await page.goto('/')`. */
28
- // baseURL: 'http://127.0.0.1:3000',
29
- /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
30
- trace: 'on-first-retry',
31
- /* allow https on localhost with self-signed certificate */
32
- ignoreHTTPSErrors: true,
33
- },
34
- /* Configure projects for major browsers */
35
- projects: [
36
- {
37
- name: 'chromium',
38
- use: { ...devices['Desktop Chrome'] },
39
- },
40
- {
41
- name: 'firefox',
42
- use: { ...devices['Desktop Firefox'] },
43
- },
44
- {
45
- name: 'webkit',
46
- use: { ...devices['Desktop Safari'] },
47
- },
48
- /* Test against mobile viewports. */
49
- // {
50
- // name: 'Mobile Chrome',
51
- // use: { ...devices['Pixel 5'] },
52
- // },
53
- // {
54
- // name: 'Mobile Safari',
55
- // use: { ...devices['iPhone 12'] },
56
- // },
57
- /* Test against branded browsers. */
58
- // {
59
- // name: 'Microsoft Edge',
60
- // use: { ...devices['Desktop Edge'], channel: 'msedge' },
61
- // },
62
- // {
63
- // name: 'Google Chrome',
64
- // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
65
- // },
66
- ],
67
- /* Run your local dev server before starting the tests */
68
- // webServer: {
69
- // command: 'npm run start',
70
- // url: 'http://127.0.0.1:3000',
71
- // reuseExistingServer: !process.env.CI,
72
- // },
73
- });