@furystack/shades-common-components 15.0.3 → 15.1.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 +55 -0
- package/esm/components/button-group.d.ts +6 -5
- package/esm/components/button-group.d.ts.map +1 -1
- package/esm/components/button-group.js +5 -1
- package/esm/components/button-group.js.map +1 -1
- package/esm/components/button-group.spec.js +5 -0
- package/esm/components/button-group.spec.js.map +1 -1
- package/esm/components/button.d.ts +3 -2
- package/esm/components/button.d.ts.map +1 -1
- package/esm/components/button.js.map +1 -1
- package/esm/components/chip.d.ts +3 -2
- package/esm/components/chip.d.ts.map +1 -1
- package/esm/components/chip.js +6 -1
- package/esm/components/chip.js.map +1 -1
- package/esm/components/chip.spec.js +16 -0
- package/esm/components/chip.spec.js.map +1 -1
- package/esm/components/component-size.d.ts +6 -0
- package/esm/components/component-size.d.ts.map +1 -0
- package/esm/components/component-size.js +2 -0
- package/esm/components/component-size.js.map +1 -0
- package/esm/components/index.d.ts +2 -0
- package/esm/components/index.d.ts.map +1 -1
- package/esm/components/index.js +2 -0
- package/esm/components/index.js.map +1 -1
- package/esm/components/inputs/checkbox.d.ts +6 -0
- package/esm/components/inputs/checkbox.d.ts.map +1 -1
- package/esm/components/inputs/checkbox.js +47 -0
- package/esm/components/inputs/checkbox.js.map +1 -1
- package/esm/components/inputs/checkbox.spec.js +38 -0
- package/esm/components/inputs/checkbox.spec.js.map +1 -1
- package/esm/components/inputs/input-number.d.ts +6 -0
- package/esm/components/inputs/input-number.d.ts.map +1 -1
- package/esm/components/inputs/input-number.js +26 -0
- package/esm/components/inputs/input-number.js.map +1 -1
- package/esm/components/inputs/input-number.spec.js +38 -0
- package/esm/components/inputs/input-number.spec.js.map +1 -1
- package/esm/components/inputs/input.d.ts +7 -1
- package/esm/components/inputs/input.d.ts.map +1 -1
- package/esm/components/inputs/input.js +24 -1
- package/esm/components/inputs/input.js.map +1 -1
- package/esm/components/inputs/input.spec.js +38 -0
- package/esm/components/inputs/input.spec.js.map +1 -1
- package/esm/components/inputs/radio.d.ts +6 -0
- package/esm/components/inputs/radio.d.ts.map +1 -1
- package/esm/components/inputs/radio.js +37 -0
- package/esm/components/inputs/radio.js.map +1 -1
- package/esm/components/inputs/radio.spec.js +38 -0
- package/esm/components/inputs/radio.spec.js.map +1 -1
- package/esm/components/inputs/select.d.ts +6 -0
- package/esm/components/inputs/select.d.ts.map +1 -1
- package/esm/components/inputs/select.js +24 -0
- package/esm/components/inputs/select.js.map +1 -1
- package/esm/components/inputs/select.spec.js +22 -0
- package/esm/components/inputs/select.spec.js.map +1 -1
- package/esm/components/inputs/switch.d.ts +2 -1
- package/esm/components/inputs/switch.d.ts.map +1 -1
- package/esm/components/inputs/switch.js +14 -1
- package/esm/components/inputs/switch.js.map +1 -1
- package/esm/components/inputs/switch.spec.js +38 -0
- package/esm/components/inputs/switch.spec.js.map +1 -1
- package/esm/components/inputs/text-area.d.ts +6 -0
- package/esm/components/inputs/text-area.d.ts.map +1 -1
- package/esm/components/inputs/text-area.js +17 -0
- package/esm/components/inputs/text-area.js.map +1 -1
- package/esm/components/inputs/text-area.spec.js +38 -0
- package/esm/components/inputs/text-area.spec.js.map +1 -1
- package/esm/components/pagination.d.ts +3 -2
- package/esm/components/pagination.d.ts.map +1 -1
- package/esm/components/pagination.js.map +1 -1
- package/esm/components/rating.d.ts +2 -1
- package/esm/components/rating.d.ts.map +1 -1
- package/esm/components/rating.js.map +1 -1
- package/esm/components/route-breadcrumb.d.ts +46 -0
- package/esm/components/route-breadcrumb.d.ts.map +1 -0
- package/esm/components/route-breadcrumb.js +56 -0
- package/esm/components/route-breadcrumb.js.map +1 -0
- package/esm/components/route-breadcrumb.spec.d.ts +2 -0
- package/esm/components/route-breadcrumb.spec.d.ts.map +1 -0
- package/esm/components/route-breadcrumb.spec.js +186 -0
- package/esm/components/route-breadcrumb.spec.js.map +1 -0
- package/esm/components/timeline.d.ts +4 -0
- package/esm/components/timeline.d.ts.map +1 -1
- package/esm/components/timeline.js +77 -1
- package/esm/components/timeline.js.map +1 -1
- package/esm/components/timeline.spec.js +74 -0
- package/esm/components/timeline.spec.js.map +1 -1
- package/package.json +2 -2
- package/src/components/button-group.spec.tsx +6 -0
- package/src/components/button-group.tsx +10 -4
- package/src/components/button.tsx +2 -1
- package/src/components/chip.spec.tsx +24 -0
- package/src/components/chip.tsx +9 -2
- package/src/components/component-size.ts +5 -0
- package/src/components/index.ts +2 -0
- package/src/components/inputs/checkbox.spec.tsx +42 -0
- package/src/components/inputs/checkbox.tsx +55 -0
- package/src/components/inputs/input-number.spec.tsx +42 -0
- package/src/components/inputs/input-number.tsx +35 -0
- package/src/components/inputs/input.spec.tsx +42 -0
- package/src/components/inputs/input.tsx +34 -2
- package/src/components/inputs/radio.spec.tsx +42 -0
- package/src/components/inputs/radio.tsx +45 -0
- package/src/components/inputs/select.spec.tsx +26 -0
- package/src/components/inputs/select.tsx +32 -0
- package/src/components/inputs/switch.spec.tsx +42 -0
- package/src/components/inputs/switch.tsx +19 -2
- package/src/components/inputs/text-area.spec.tsx +42 -0
- package/src/components/inputs/text-area.tsx +25 -0
- package/src/components/pagination.tsx +2 -1
- package/src/components/rating.tsx +2 -1
- package/src/components/route-breadcrumb.spec.tsx +239 -0
- package/src/components/route-breadcrumb.tsx +83 -0
- package/src/components/timeline.spec.tsx +109 -0
- package/src/components/timeline.tsx +94 -1
|
@@ -3,6 +3,7 @@ import { Shade, createComponent } from '@furystack/shades'
|
|
|
3
3
|
import { cssVariableTheme } from '../../services/css-variable-theme.js'
|
|
4
4
|
import type { Palette } from '../../services/theme-provider-service.js'
|
|
5
5
|
import { ThemeProviderService } from '../../services/theme-provider-service.js'
|
|
6
|
+
import type { ComponentSize } from '../component-size.js'
|
|
6
7
|
import { FormService } from '../form.js'
|
|
7
8
|
|
|
8
9
|
const emptyValidity = {} as ValidityState
|
|
@@ -13,7 +14,7 @@ export type InvalidInputValidationResult = { isValid: false; message: string }
|
|
|
13
14
|
|
|
14
15
|
export type InputValidationResult = ValidInputValidationResult | InvalidInputValidationResult
|
|
15
16
|
|
|
16
|
-
export interface TextInputProps extends PartialElement<HTMLInputElement> {
|
|
17
|
+
export interface TextInputProps extends Omit<PartialElement<HTMLInputElement>, 'size'> {
|
|
17
18
|
/**
|
|
18
19
|
* Callback that will be called when the input value changes
|
|
19
20
|
*/
|
|
@@ -36,6 +37,12 @@ export interface TextInputProps extends PartialElement<HTMLInputElement> {
|
|
|
36
37
|
* The variant of the input
|
|
37
38
|
*/
|
|
38
39
|
variant?: 'contained' | 'outlined'
|
|
40
|
+
/**
|
|
41
|
+
* The size of the input.
|
|
42
|
+
* @default 'medium'
|
|
43
|
+
*/
|
|
44
|
+
size?: ComponentSize
|
|
45
|
+
|
|
39
46
|
/**
|
|
40
47
|
* The default color of the input (Error color will be used in case of invalid input value)
|
|
41
48
|
*/
|
|
@@ -223,8 +230,32 @@ export const Input = Shade<TextInputProps>({
|
|
|
223
230
|
alignItems: 'center',
|
|
224
231
|
fontSize: cssVariableTheme.typography.fontSize.lg,
|
|
225
232
|
},
|
|
233
|
+
|
|
234
|
+
// Size: small
|
|
235
|
+
'&[data-size="small"] label': {
|
|
236
|
+
padding: `${cssVariableTheme.spacing.xs} ${cssVariableTheme.spacing.sm}`,
|
|
237
|
+
},
|
|
238
|
+
'&[data-size="small"] input': {
|
|
239
|
+
fontSize: cssVariableTheme.typography.fontSize.xs,
|
|
240
|
+
},
|
|
241
|
+
'&[data-size="small"] .startIcon, &[data-size="small"] .endIcon': {
|
|
242
|
+
fontSize: cssVariableTheme.typography.fontSize.md,
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
// Size: large
|
|
246
|
+
'&[data-size="large"] label': {
|
|
247
|
+
padding: `${cssVariableTheme.spacing.md} ${cssVariableTheme.spacing.lg}`,
|
|
248
|
+
fontSize: cssVariableTheme.typography.fontSize.sm,
|
|
249
|
+
},
|
|
250
|
+
'&[data-size="large"] input': {
|
|
251
|
+
fontSize: cssVariableTheme.typography.fontSize.md,
|
|
252
|
+
},
|
|
253
|
+
'&[data-size="large"] .startIcon, &[data-size="large"] .endIcon': {
|
|
254
|
+
fontSize: cssVariableTheme.typography.fontSize.xl,
|
|
255
|
+
},
|
|
226
256
|
},
|
|
227
257
|
render: ({ props, injector, useState, useDisposable, useHostProps, useRef }) => {
|
|
258
|
+
const { size: componentSize, ...nativeProps } = props
|
|
228
259
|
const inputRef = useRef<HTMLInputElement>('formInput')
|
|
229
260
|
|
|
230
261
|
useDisposable('form-registration', () => {
|
|
@@ -277,6 +308,7 @@ export const Input = Shade<TextInputProps>({
|
|
|
277
308
|
const primaryColor = themeProvider.theme.palette[props.defaultColor || 'primary'].main
|
|
278
309
|
useHostProps({
|
|
279
310
|
'data-variant': props.variant || undefined,
|
|
311
|
+
'data-size': componentSize && componentSize !== 'medium' ? componentSize : undefined,
|
|
280
312
|
'data-disabled': props.disabled ? '' : undefined,
|
|
281
313
|
'data-invalid': isInvalid ? '' : undefined,
|
|
282
314
|
style: {
|
|
@@ -324,7 +356,7 @@ export const Input = Shade<TextInputProps>({
|
|
|
324
356
|
setFocused(false)
|
|
325
357
|
setValidity((ev.target as HTMLInputElement).validity)
|
|
326
358
|
}}
|
|
327
|
-
{...
|
|
359
|
+
{...nativeProps}
|
|
328
360
|
style={props.style}
|
|
329
361
|
{...(props.value !== undefined ? { value: props.value } : {})}
|
|
330
362
|
/>
|
|
@@ -270,4 +270,46 @@ describe('Radio', () => {
|
|
|
270
270
|
})
|
|
271
271
|
})
|
|
272
272
|
})
|
|
273
|
+
|
|
274
|
+
describe('size', () => {
|
|
275
|
+
it('should not set data-size when size is not specified', async () => {
|
|
276
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
277
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
278
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <Radio value="opt1" /> })
|
|
279
|
+
await flushUpdates()
|
|
280
|
+
const el = document.querySelector('shade-radio') as HTMLElement
|
|
281
|
+
expect(el.getAttribute('data-size')).toBeNull()
|
|
282
|
+
})
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
it('should not set data-size for medium size (default)', async () => {
|
|
286
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
287
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
288
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <Radio value="opt1" size="medium" /> })
|
|
289
|
+
await flushUpdates()
|
|
290
|
+
const el = document.querySelector('shade-radio') as HTMLElement
|
|
291
|
+
expect(el.getAttribute('data-size')).toBeNull()
|
|
292
|
+
})
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('should set data-size="small" for small size', async () => {
|
|
296
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
297
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
298
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <Radio value="opt1" size="small" /> })
|
|
299
|
+
await flushUpdates()
|
|
300
|
+
const el = document.querySelector('shade-radio') as HTMLElement
|
|
301
|
+
expect(el.getAttribute('data-size')).toBe('small')
|
|
302
|
+
})
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('should set data-size="large" for large size', async () => {
|
|
306
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
307
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
308
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <Radio value="opt1" size="large" /> })
|
|
309
|
+
await flushUpdates()
|
|
310
|
+
const el = document.querySelector('shade-radio') as HTMLElement
|
|
311
|
+
expect(el.getAttribute('data-size')).toBe('large')
|
|
312
|
+
})
|
|
313
|
+
})
|
|
314
|
+
})
|
|
273
315
|
})
|
|
@@ -3,6 +3,7 @@ import { Shade, createComponent } from '@furystack/shades'
|
|
|
3
3
|
import { cssVariableTheme } from '../../services/css-variable-theme.js'
|
|
4
4
|
import type { Palette } from '../../services/theme-provider-service.js'
|
|
5
5
|
import { ThemeProviderService } from '../../services/theme-provider-service.js'
|
|
6
|
+
import type { ComponentSize } from '../component-size.js'
|
|
6
7
|
import { FormService } from '../form.js'
|
|
7
8
|
|
|
8
9
|
export type RadioProps = {
|
|
@@ -34,6 +35,11 @@ export type RadioProps = {
|
|
|
34
35
|
* Whether the radio button is checked
|
|
35
36
|
*/
|
|
36
37
|
checked?: boolean
|
|
38
|
+
/**
|
|
39
|
+
* The size of the radio button.
|
|
40
|
+
* @default 'medium'
|
|
41
|
+
*/
|
|
42
|
+
size?: ComponentSize
|
|
37
43
|
/**
|
|
38
44
|
* Optional props for the label element
|
|
39
45
|
*/
|
|
@@ -116,6 +122,44 @@ export const Radio = Shade<RadioProps>({
|
|
|
116
122
|
opacity: cssVariableTheme.action.disabledOpacity,
|
|
117
123
|
cursor: 'not-allowed',
|
|
118
124
|
},
|
|
125
|
+
|
|
126
|
+
// Size: small
|
|
127
|
+
'&[data-size="small"] label': {
|
|
128
|
+
fontSize: cssVariableTheme.typography.fontSize.xs,
|
|
129
|
+
},
|
|
130
|
+
'&[data-size="small"] .radio-control': {
|
|
131
|
+
width: '16px',
|
|
132
|
+
height: '16px',
|
|
133
|
+
},
|
|
134
|
+
'&[data-size="small"] input[type="radio"]': {
|
|
135
|
+
width: '16px',
|
|
136
|
+
height: '16px',
|
|
137
|
+
},
|
|
138
|
+
'&[data-size="small"] input[type="radio"]:checked::after': {
|
|
139
|
+
left: '4px',
|
|
140
|
+
top: '4px',
|
|
141
|
+
width: '8px',
|
|
142
|
+
height: '8px',
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
// Size: large
|
|
146
|
+
'&[data-size="large"] label': {
|
|
147
|
+
fontSize: cssVariableTheme.typography.fontSize.md,
|
|
148
|
+
},
|
|
149
|
+
'&[data-size="large"] .radio-control': {
|
|
150
|
+
width: '24px',
|
|
151
|
+
height: '24px',
|
|
152
|
+
},
|
|
153
|
+
'&[data-size="large"] input[type="radio"]': {
|
|
154
|
+
width: '24px',
|
|
155
|
+
height: '24px',
|
|
156
|
+
},
|
|
157
|
+
'&[data-size="large"] input[type="radio"]:checked::after': {
|
|
158
|
+
left: '6px',
|
|
159
|
+
top: '6px',
|
|
160
|
+
width: '12px',
|
|
161
|
+
height: '12px',
|
|
162
|
+
},
|
|
119
163
|
},
|
|
120
164
|
render: ({ props, injector, useDisposable, useHostProps, useRef }) => {
|
|
121
165
|
const inputRef = useRef<HTMLInputElement>('formInput')
|
|
@@ -177,6 +221,7 @@ export const Radio = Shade<RadioProps>({
|
|
|
177
221
|
|
|
178
222
|
const color = themeProvider.theme.palette[props.color || 'primary'].main
|
|
179
223
|
useHostProps({
|
|
224
|
+
'data-size': props.size && props.size !== 'medium' ? props.size : undefined,
|
|
180
225
|
'data-disabled': isDisabled ? '' : undefined,
|
|
181
226
|
style: { '--radio-color': color },
|
|
182
227
|
})
|
|
@@ -1231,4 +1231,30 @@ describe('Select', () => {
|
|
|
1231
1231
|
})
|
|
1232
1232
|
})
|
|
1233
1233
|
})
|
|
1234
|
+
|
|
1235
|
+
describe('size', () => {
|
|
1236
|
+
it('should not set data-size when size is not specified', async () => {
|
|
1237
|
+
await usingAsync(await renderSelect({ options: defaultOptions }), async ({ select }) => {
|
|
1238
|
+
expect(select.getAttribute('data-size')).toBeNull()
|
|
1239
|
+
})
|
|
1240
|
+
})
|
|
1241
|
+
|
|
1242
|
+
it('should not set data-size for medium size (default)', async () => {
|
|
1243
|
+
await usingAsync(await renderSelect({ options: defaultOptions, size: 'medium' }), async ({ select }) => {
|
|
1244
|
+
expect(select.getAttribute('data-size')).toBeNull()
|
|
1245
|
+
})
|
|
1246
|
+
})
|
|
1247
|
+
|
|
1248
|
+
it('should set data-size="small" for small size', async () => {
|
|
1249
|
+
await usingAsync(await renderSelect({ options: defaultOptions, size: 'small' }), async ({ select }) => {
|
|
1250
|
+
expect(select.getAttribute('data-size')).toBe('small')
|
|
1251
|
+
})
|
|
1252
|
+
})
|
|
1253
|
+
|
|
1254
|
+
it('should set data-size="large" for large size', async () => {
|
|
1255
|
+
await usingAsync(await renderSelect({ options: defaultOptions, size: 'large' }), async ({ select }) => {
|
|
1256
|
+
expect(select.getAttribute('data-size')).toBe('large')
|
|
1257
|
+
})
|
|
1258
|
+
})
|
|
1259
|
+
})
|
|
1234
1260
|
})
|
|
@@ -3,6 +3,7 @@ import { Shade, createComponent } from '@furystack/shades'
|
|
|
3
3
|
import { cssVariableTheme } from '../../services/css-variable-theme.js'
|
|
4
4
|
import type { Palette } from '../../services/theme-provider-service.js'
|
|
5
5
|
import { ThemeProviderService } from '../../services/theme-provider-service.js'
|
|
6
|
+
import type { ComponentSize } from '../component-size.js'
|
|
6
7
|
import { FormService } from '../form.js'
|
|
7
8
|
import { check, close } from '../icons/icon-definitions.js'
|
|
8
9
|
import { Icon } from '../icons/icon.js'
|
|
@@ -47,6 +48,11 @@ export type SelectProps = {
|
|
|
47
48
|
labelProps?: PartialElement<HTMLLabelElement>
|
|
48
49
|
/** The visual variant of the select */
|
|
49
50
|
variant?: 'contained' | 'outlined'
|
|
51
|
+
/**
|
|
52
|
+
* The size of the select.
|
|
53
|
+
* @default 'medium'
|
|
54
|
+
*/
|
|
55
|
+
size?: ComponentSize
|
|
50
56
|
/** The default color of the select */
|
|
51
57
|
defaultColor?: keyof Palette
|
|
52
58
|
/** The name attribute for form integration */
|
|
@@ -340,6 +346,31 @@ export const Select = Shade<SelectProps>({
|
|
|
340
346
|
opacity: '0.85',
|
|
341
347
|
lineHeight: '1.4',
|
|
342
348
|
},
|
|
349
|
+
|
|
350
|
+
// Size: small
|
|
351
|
+
'&[data-size="small"] label': {
|
|
352
|
+
padding: `${cssVariableTheme.spacing.xs} ${cssVariableTheme.spacing.sm}`,
|
|
353
|
+
},
|
|
354
|
+
'&[data-size="small"] .select-value': {
|
|
355
|
+
fontSize: cssVariableTheme.typography.fontSize.xs,
|
|
356
|
+
},
|
|
357
|
+
'&[data-size="small"] .dropdown-item': {
|
|
358
|
+
padding: `6px ${cssVariableTheme.spacing.sm}`,
|
|
359
|
+
fontSize: cssVariableTheme.typography.fontSize.xs,
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
// Size: large
|
|
363
|
+
'&[data-size="large"] label': {
|
|
364
|
+
padding: `${cssVariableTheme.spacing.md} ${cssVariableTheme.spacing.lg}`,
|
|
365
|
+
fontSize: cssVariableTheme.typography.fontSize.sm,
|
|
366
|
+
},
|
|
367
|
+
'&[data-size="large"] .select-value': {
|
|
368
|
+
fontSize: cssVariableTheme.typography.fontSize.md,
|
|
369
|
+
},
|
|
370
|
+
'&[data-size="large"] .dropdown-item': {
|
|
371
|
+
padding: `${cssVariableTheme.spacing.sm} ${cssVariableTheme.spacing.lg}`,
|
|
372
|
+
fontSize: cssVariableTheme.typography.fontSize.md,
|
|
373
|
+
},
|
|
343
374
|
},
|
|
344
375
|
render: ({ props, injector, useState, useDisposable, useHostProps, useRef }) => {
|
|
345
376
|
const selectRootRef = useRef<HTMLDivElement>('selectRoot')
|
|
@@ -394,6 +425,7 @@ export const Select = Shade<SelectProps>({
|
|
|
394
425
|
const primaryColor = themeProvider.theme.palette[props.defaultColor || 'primary'].main
|
|
395
426
|
useHostProps({
|
|
396
427
|
'data-variant': props.variant || undefined,
|
|
428
|
+
'data-size': props.size && props.size !== 'medium' ? props.size : undefined,
|
|
397
429
|
'data-disabled': props.disabled ? '' : undefined,
|
|
398
430
|
'data-multiple': isMultiple ? '' : undefined,
|
|
399
431
|
'data-open': state.isOpen && !props.disabled ? '' : undefined,
|
|
@@ -407,4 +407,46 @@ describe('Switch', () => {
|
|
|
407
407
|
})
|
|
408
408
|
})
|
|
409
409
|
})
|
|
410
|
+
|
|
411
|
+
describe('size', () => {
|
|
412
|
+
it('should not set data-size when size is not specified', async () => {
|
|
413
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
414
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
415
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <Switch /> })
|
|
416
|
+
await flushUpdates()
|
|
417
|
+
const el = document.querySelector('shade-switch') as HTMLElement
|
|
418
|
+
expect(el.getAttribute('data-size')).toBeNull()
|
|
419
|
+
})
|
|
420
|
+
})
|
|
421
|
+
|
|
422
|
+
it('should not set data-size for medium size (default)', async () => {
|
|
423
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
424
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
425
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <Switch size="medium" /> })
|
|
426
|
+
await flushUpdates()
|
|
427
|
+
const el = document.querySelector('shade-switch') as HTMLElement
|
|
428
|
+
expect(el.getAttribute('data-size')).toBeNull()
|
|
429
|
+
})
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
it('should set data-size="small" for small size', async () => {
|
|
433
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
434
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
435
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <Switch size="small" /> })
|
|
436
|
+
await flushUpdates()
|
|
437
|
+
const el = document.querySelector('shade-switch') as HTMLElement
|
|
438
|
+
expect(el.getAttribute('data-size')).toBe('small')
|
|
439
|
+
})
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
it('should set data-size="large" for large size', async () => {
|
|
443
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
444
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
445
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <Switch size="large" /> })
|
|
446
|
+
await flushUpdates()
|
|
447
|
+
const el = document.querySelector('shade-switch') as HTMLElement
|
|
448
|
+
expect(el.getAttribute('data-size')).toBe('large')
|
|
449
|
+
})
|
|
450
|
+
})
|
|
451
|
+
})
|
|
410
452
|
})
|
|
@@ -3,6 +3,7 @@ import { Shade, createComponent } from '@furystack/shades'
|
|
|
3
3
|
import { buildTransition, cssVariableTheme } from '../../services/css-variable-theme.js'
|
|
4
4
|
import type { Palette } from '../../services/theme-provider-service.js'
|
|
5
5
|
import { ThemeProviderService } from '../../services/theme-provider-service.js'
|
|
6
|
+
import type { ComponentSize } from '../component-size.js'
|
|
6
7
|
import { FormService } from '../form.js'
|
|
7
8
|
|
|
8
9
|
export type SwitchProps = {
|
|
@@ -41,7 +42,7 @@ export type SwitchProps = {
|
|
|
41
42
|
/**
|
|
42
43
|
* The size of the switch
|
|
43
44
|
*/
|
|
44
|
-
size?:
|
|
45
|
+
size?: ComponentSize
|
|
45
46
|
/**
|
|
46
47
|
* Optional props for the label element
|
|
47
48
|
*/
|
|
@@ -116,6 +117,18 @@ export const Switch = Shade<SwitchProps>({
|
|
|
116
117
|
height: '14px',
|
|
117
118
|
},
|
|
118
119
|
|
|
120
|
+
// Large size
|
|
121
|
+
'&[data-size="large"] .switch-track': {
|
|
122
|
+
width: '48px',
|
|
123
|
+
height: '26px',
|
|
124
|
+
borderRadius: '13px',
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
'&[data-size="large"] .switch-thumb': {
|
|
128
|
+
width: '22px',
|
|
129
|
+
height: '22px',
|
|
130
|
+
},
|
|
131
|
+
|
|
119
132
|
// Hidden input
|
|
120
133
|
'& input[type="checkbox"]': {
|
|
121
134
|
position: 'absolute',
|
|
@@ -143,6 +156,10 @@ export const Switch = Shade<SwitchProps>({
|
|
|
143
156
|
transform: 'translateX(14px)',
|
|
144
157
|
},
|
|
145
158
|
|
|
159
|
+
'&[data-size="large"] input[type="checkbox"]:checked + .switch-track .switch-thumb': {
|
|
160
|
+
transform: 'translateX(22px)',
|
|
161
|
+
},
|
|
162
|
+
|
|
146
163
|
// Hover state
|
|
147
164
|
'& .switch-control:hover .switch-track': {
|
|
148
165
|
opacity: '0.7',
|
|
@@ -191,7 +208,7 @@ export const Switch = Shade<SwitchProps>({
|
|
|
191
208
|
const color = themeProvider.theme.palette[props.color || 'primary'].main
|
|
192
209
|
useHostProps({
|
|
193
210
|
'data-disabled': props.disabled ? '' : undefined,
|
|
194
|
-
'data-size': props.size
|
|
211
|
+
'data-size': props.size && props.size !== 'medium' ? props.size : undefined,
|
|
195
212
|
style: { '--switch-color': color },
|
|
196
213
|
})
|
|
197
214
|
|
|
@@ -297,4 +297,46 @@ describe('TextArea', () => {
|
|
|
297
297
|
expect(computedStyle.marginBottom).toBe('1em')
|
|
298
298
|
})
|
|
299
299
|
})
|
|
300
|
+
|
|
301
|
+
describe('size', () => {
|
|
302
|
+
it('should not set data-size when size is not specified', async () => {
|
|
303
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
304
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
305
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <TextArea /> })
|
|
306
|
+
await flushUpdates()
|
|
307
|
+
const el = document.querySelector('shade-text-area') as HTMLElement
|
|
308
|
+
expect(el.getAttribute('data-size')).toBeNull()
|
|
309
|
+
})
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
it('should not set data-size for medium size (default)', async () => {
|
|
313
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
314
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
315
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <TextArea size="medium" /> })
|
|
316
|
+
await flushUpdates()
|
|
317
|
+
const el = document.querySelector('shade-text-area') as HTMLElement
|
|
318
|
+
expect(el.getAttribute('data-size')).toBeNull()
|
|
319
|
+
})
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
it('should set data-size="small" for small size', async () => {
|
|
323
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
324
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
325
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <TextArea size="small" /> })
|
|
326
|
+
await flushUpdates()
|
|
327
|
+
const el = document.querySelector('shade-text-area') as HTMLElement
|
|
328
|
+
expect(el.getAttribute('data-size')).toBe('small')
|
|
329
|
+
})
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
it('should set data-size="large" for large size', async () => {
|
|
333
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
334
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
335
|
+
initializeShadeRoot({ injector, rootElement, jsxElement: <TextArea size="large" /> })
|
|
336
|
+
await flushUpdates()
|
|
337
|
+
const el = document.querySelector('shade-text-area') as HTMLElement
|
|
338
|
+
expect(el.getAttribute('data-size')).toBe('large')
|
|
339
|
+
})
|
|
340
|
+
})
|
|
341
|
+
})
|
|
300
342
|
})
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { PartialElement } from '@furystack/shades'
|
|
2
2
|
import { createComponent, Shade } from '@furystack/shades'
|
|
3
3
|
import { cssVariableTheme } from '../../services/css-variable-theme.js'
|
|
4
|
+
import type { ComponentSize } from '../component-size.js'
|
|
4
5
|
|
|
5
6
|
export interface TextAreaProps extends PartialElement<HTMLTextAreaElement> {
|
|
6
7
|
labelTitle?: string
|
|
7
8
|
labelProps?: PartialElement<HTMLLabelElement>
|
|
8
9
|
autofocus?: boolean
|
|
9
10
|
variant?: 'contained' | 'outlined'
|
|
11
|
+
/**
|
|
12
|
+
* The size of the text area.
|
|
13
|
+
* @default 'medium'
|
|
14
|
+
*/
|
|
15
|
+
size?: ComponentSize
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
export const TextArea = Shade<TextAreaProps>({
|
|
@@ -49,10 +55,29 @@ export const TextArea = Shade<TextAreaProps>({
|
|
|
49
55
|
'&:focus-within .textarea-content': {
|
|
50
56
|
boxShadow: `0px 3px 0px ${cssVariableTheme.palette.primary.main}`,
|
|
51
57
|
},
|
|
58
|
+
|
|
59
|
+
// Size: small
|
|
60
|
+
'&[data-size="small"] label': {
|
|
61
|
+
padding: cssVariableTheme.spacing.sm,
|
|
62
|
+
fontSize: cssVariableTheme.typography.fontSize.xs,
|
|
63
|
+
},
|
|
64
|
+
'&[data-size="small"] .textarea-content': {
|
|
65
|
+
fontSize: cssVariableTheme.typography.fontSize.xs,
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
// Size: large
|
|
69
|
+
'&[data-size="large"] label': {
|
|
70
|
+
padding: cssVariableTheme.spacing.lg,
|
|
71
|
+
fontSize: cssVariableTheme.typography.fontSize.sm,
|
|
72
|
+
},
|
|
73
|
+
'&[data-size="large"] .textarea-content': {
|
|
74
|
+
fontSize: cssVariableTheme.typography.fontSize.md,
|
|
75
|
+
},
|
|
52
76
|
},
|
|
53
77
|
render: ({ props, useHostProps }) => {
|
|
54
78
|
useHostProps({
|
|
55
79
|
'data-variant': props.variant || undefined,
|
|
80
|
+
'data-size': props.size && props.size !== 'medium' ? props.size : undefined,
|
|
56
81
|
'data-disabled': props.disabled ? '' : undefined,
|
|
57
82
|
})
|
|
58
83
|
|
|
@@ -3,6 +3,7 @@ import { Shade, createComponent } from '@furystack/shades'
|
|
|
3
3
|
import { buildTransition, cssVariableTheme } from '../services/css-variable-theme.js'
|
|
4
4
|
import { paletteMainColors } from '../services/palette-css-vars.js'
|
|
5
5
|
import type { Palette } from '../services/theme-provider-service.js'
|
|
6
|
+
import type { ComponentSize } from './component-size.js'
|
|
6
7
|
|
|
7
8
|
export type PaginationProps = PartialElement<HTMLElement> & {
|
|
8
9
|
/** Total number of pages */
|
|
@@ -18,7 +19,7 @@ export type PaginationProps = PartialElement<HTMLElement> & {
|
|
|
18
19
|
/** If true, the pagination is disabled */
|
|
19
20
|
disabled?: boolean
|
|
20
21
|
/** Size variant */
|
|
21
|
-
size?:
|
|
22
|
+
size?: ComponentSize
|
|
22
23
|
/** Palette color */
|
|
23
24
|
color?: keyof Palette
|
|
24
25
|
}
|
|
@@ -2,6 +2,7 @@ import { Shade, createComponent } from '@furystack/shades'
|
|
|
2
2
|
import { buildTransition, cssVariableTheme } from '../services/css-variable-theme.js'
|
|
3
3
|
import type { Palette } from '../services/theme-provider-service.js'
|
|
4
4
|
import { ThemeProviderService } from '../services/theme-provider-service.js'
|
|
5
|
+
import type { ComponentSize } from './component-size.js'
|
|
5
6
|
import { Icon } from './icons/icon.js'
|
|
6
7
|
import { star as starIcon, starOutline } from './icons/icon-definitions.js'
|
|
7
8
|
|
|
@@ -24,7 +25,7 @@ export type RatingProps = {
|
|
|
24
25
|
/**
|
|
25
26
|
* Size of the rating stars
|
|
26
27
|
*/
|
|
27
|
-
size?:
|
|
28
|
+
size?: ComponentSize
|
|
28
29
|
/**
|
|
29
30
|
* Whether the rating is disabled
|
|
30
31
|
*/
|