@sakura-ui/sakura-ui 0.4.1 → 0.5.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.
Files changed (38) hide show
  1. package/README.md +87 -0
  2. package/package.json +3 -3
  3. package/packages/core/package.json +1 -1
  4. package/packages/core/src/components/Card.tsx +51 -32
  5. package/packages/core/src/components/Faq.tsx +8 -24
  6. package/packages/core/src/components/LinkCard.tsx +103 -54
  7. package/packages/core/src/components/index.ts +1 -0
  8. package/packages/core/src/index.ts +2 -0
  9. package/packages/core/tests/Card.test.tsx +124 -20
  10. package/packages/core/tests/Faq.test.tsx +75 -0
  11. package/packages/core/tests/LinkCard.test.tsx +151 -0
  12. package/packages/forms/.turbo/turbo-build.log +3 -3
  13. package/packages/forms/dist/index.cjs.js +18 -18
  14. package/packages/forms/dist/index.es.js +166 -178
  15. package/packages/forms/dist/types/components/Checkbox.d.ts.map +1 -1
  16. package/packages/forms/dist/types/components/FileInput.d.ts.map +1 -1
  17. package/packages/forms/dist/types/components/Input.d.ts.map +1 -1
  18. package/packages/forms/dist/types/components/Radio.d.ts.map +1 -1
  19. package/packages/forms/dist/types/components/Select.d.ts.map +1 -1
  20. package/packages/forms/dist/types/components/Textarea.d.ts.map +1 -1
  21. package/packages/forms/package.json +1 -1
  22. package/packages/forms/src/components/Checkbox.tsx +0 -1
  23. package/packages/forms/src/components/FileInput.tsx +3 -8
  24. package/packages/forms/src/components/Input.tsx +0 -1
  25. package/packages/forms/src/components/Radio.tsx +0 -3
  26. package/packages/forms/src/components/Select.tsx +0 -1
  27. package/packages/forms/src/components/Textarea.tsx +0 -1
  28. package/packages/forms/tests/FileInput.test.tsx +30 -5
  29. package/packages/helper/.turbo/turbo-build.log +1 -1
  30. package/packages/markdown/.turbo/turbo-build.log +4 -4
  31. package/packages/markdown/dist/index.cjs.js +23 -23
  32. package/packages/markdown/dist/index.es.js +1732 -1727
  33. package/packages/markdown/dist/types/components/Markdown.d.ts.map +1 -1
  34. package/packages/markdown/dist/types/plugins/card.d.ts.map +1 -1
  35. package/packages/markdown/package.json +3 -2
  36. package/packages/markdown/src/components/Markdown.tsx +35 -11
  37. package/packages/markdown/src/plugins/card.ts +14 -0
  38. package/packages/tailwind-theme-plugin/.turbo/turbo-build.log +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/Checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,cAAc,CAAA;AAErB,yBAAiB,QAAQ,CAAC;IACxB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QACzE,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,QAAQ;YAAW,QAAQ,CAAC,KAAK;;CA0E7C,CAAA"}
1
+ {"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/Checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,cAAc,CAAA;AAErB,yBAAiB,QAAQ,CAAC;IACxB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QACzE,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,QAAQ;YAAW,QAAQ,CAAC,KAAK;;CAyE7C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"FileInput.d.ts","sourceRoot":"","sources":["../../../src/components/FileInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,yBAAiB,SAAS,CAAC;IACzB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QACzE,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,SAAS;YAAW,SAAS,CAAC,KAAK;;CA2F/C,CAAA"}
1
+ {"version":3,"file":"FileInput.d.ts","sourceRoot":"","sources":["../../../src/components/FileInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,yBAAiB,SAAS,CAAC;IACzB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QACzE,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,SAAS;YAAW,SAAS,CAAC,KAAK;;CAsF/C,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,cAAc,CAAA;AAErB,yBAAiB,KAAK,CAAC;IACrB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QACzE,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,KAAK;YAAW,KAAK,CAAC,KAAK;;CAuBvC,CAAA"}
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,cAAc,CAAA;AAErB,yBAAiB,KAAK,CAAC;IACrB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QACzE,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,KAAK;YAAW,KAAK,CAAC,KAAK;;CAsBvC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../src/components/Radio.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,cAAc,CAAA;AAErB,yBAAiB,KAAK,CAAC;IACrB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QACzE,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,KAAK;YAAW,KAAK,CAAC,KAAK;;CAiEvC,CAAA"}
1
+ {"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../src/components/Radio.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,cAAc,CAAA;AAErB,yBAAiB,KAAK,CAAC;IACrB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QACzE,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,KAAK;YAAW,KAAK,CAAC,KAAK;;CA8DvC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/Select.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,cAAc,CAAA;AAErB,yBAAiB,MAAM,CAAC;IACtB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC1E,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,MAAM;YAAW,MAAM,CAAC,KAAK;;CA2DzC,CAAA"}
1
+ {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/Select.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAGzD,OAAO,EACL,KAAK,SAAS,EAGf,MAAM,cAAc,CAAA;AAErB,yBAAiB,MAAM,CAAC;IACtB,UAAiB,KAAM,SAAQ,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC1E,IAAI,CAAC,EAAE,SAAS,CAAA;KACjB;CACF;AAED,eAAO,MAAM,MAAM;YAAW,MAAM,CAAC,KAAK;;CA0DzC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../../src/components/Textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAIzD,yBAAiB,QAAQ,CAAC;IACxB,UAAiB,KAAM,SAAQ,qBAAqB,CAAC,UAAU,CAAC;KAAG;CACpE;AAED,eAAO,MAAM,QAAQ;YAAW,QAAQ,CAAC,KAAK;;CAyD7C,CAAA"}
1
+ {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../../src/components/Textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAA;AAIzD,yBAAiB,QAAQ,CAAC;IACxB,UAAiB,KAAM,SAAQ,qBAAqB,CAAC,UAAU,CAAC;KAAG;CACpE;AAED,eAAO,MAAM,QAAQ;YAAW,QAAQ,CAAC,KAAK;;CAwD7C,CAAA"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sakura-ui/forms",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "author": "glassonion1",
@@ -68,7 +68,6 @@ export const Checkbox = (props: Checkbox.Props) => {
68
68
  aria-describedby={ctx.helperTextId}
69
69
  aria-errormessage={ctx.errorMessageId}
70
70
  aria-invalid={ctx.isInvalid ?? false}
71
- aria-required={ctx.isRequired ?? false}
72
71
  {...restProps}
73
72
  />
74
73
  <span className={cx(styleCheck, iconStyles[size])}>
@@ -81,12 +81,10 @@ export const FileInput = (props: FileInput.Props) => {
81
81
  `
82
82
  }
83
83
 
84
- // TODO: aria-required is not valid on input[type=file] and role="button" does not
85
- // describe a file picker. Both need to be reworked (the required attribute changes
86
- // form submission behaviour), so they are tracked separately from this change.
84
+ // The accessible name comes from the associated label (LabelControl, or a label
85
+ // supplied by the caller). Do not set aria-label here: it would override that name
86
+ // and every file input on a page would announce the same thing.
87
87
  return (
88
- // biome-ignore lint/a11y/useAriaPropsSupportedByRole: see the TODO above
89
- // biome-ignore lint/a11y/useSemanticElements: see the TODO above
90
88
  <input
91
89
  type="file"
92
90
  id={id || ctx.id}
@@ -94,9 +92,6 @@ export const FileInput = (props: FileInput.Props) => {
94
92
  aria-describedby={ctx.helperTextId}
95
93
  aria-errormessage={ctx.errorMessageId}
96
94
  aria-invalid={ctx.isInvalid ?? false}
97
- aria-required={ctx.isRequired ?? false}
98
- role="button"
99
- aria-label="File Upload"
100
95
  {...restProps}
101
96
  />
102
97
  )
@@ -32,7 +32,6 @@ export const Input = (props: Input.Props) => {
32
32
  aria-describedby={ctx.helperTextId}
33
33
  aria-errormessage={ctx.errorMessageId}
34
34
  aria-invalid={ctx.isInvalid ?? false}
35
- aria-required={ctx.isRequired ?? false}
36
35
  {...restProps}
37
36
  />
38
37
  )
@@ -59,8 +59,6 @@ export const Radio = (props: Radio.Props) => {
59
59
  )}
60
60
  >
61
61
  <span className="flex items-center">
62
- {/* TODO: aria-required belongs on the radiogroup (FieldsetControl), not on each radio */}
63
- {/* biome-ignore lint/a11y/useAriaPropsSupportedByRole: see the TODO above */}
64
62
  <input
65
63
  id={radioId}
66
64
  className={styleInput}
@@ -68,7 +66,6 @@ export const Radio = (props: Radio.Props) => {
68
66
  aria-describedby={ctx.helperTextId}
69
67
  aria-errormessage={ctx.errorMessageId}
70
68
  aria-invalid={ctx.isInvalid ?? false}
71
- aria-required={ctx.isRequired ?? false}
72
69
  {...restProps}
73
70
  />
74
71
  <span
@@ -50,7 +50,6 @@ export const Select = (props: Select.Props) => {
50
50
  aria-describedby={ctx.helperTextId}
51
51
  aria-errormessage={ctx.errorMessageId}
52
52
  aria-invalid={ctx.isInvalid ?? false}
53
- aria-required={ctx.isRequired ?? false}
54
53
  {...restProps}
55
54
  >
56
55
  {children}
@@ -47,7 +47,6 @@ export const Textarea = (props: Textarea.Props) => {
47
47
  aria-describedby={ctx.helperTextId}
48
48
  aria-errormessage={ctx.errorMessageId}
49
49
  aria-invalid={ctx.isInvalid ?? false}
50
- aria-required={ctx.isRequired ?? false}
51
50
  onChange={onChangeHandler}
52
51
  {...restProps}
53
52
  >
@@ -2,17 +2,42 @@ import React from 'react'
2
2
  import { describe, it, expect, vi } from 'vitest'
3
3
  import { render, screen } from '@testing-library/react'
4
4
 
5
- import { FileInput } from '../src'
5
+ import { FileInput, LabelControl } from '../src'
6
6
 
7
7
  describe('FileInput', () => {
8
- it('should render a file input with a label text', async () => {
9
- render(<FileInput />)
8
+ it('should render a file input', async () => {
9
+ // input[type=file] maps to no ARIA role, so it cannot be queried by role
10
+ const { container } = render(<FileInput />)
10
11
 
11
- const input = screen.getByRole('button')
12
+ const input = container.querySelector('input[type="file"]')
12
13
 
13
14
  expect(input).toBeInTheDocument()
15
+ })
16
+
17
+ it('should take its accessible name from the surrounding label', async () => {
18
+ render(
19
+ <LabelControl labelText="添付書類">
20
+ <FileInput />
21
+ </LabelControl>
22
+ )
23
+
24
+ const input = screen.getByLabelText('添付書類')
25
+
26
+ expect(input).toBeInTheDocument()
27
+ // Asserting the accessible name rather than using getByLabelText alone:
28
+ // getByLabelText also matches aria-label, so it would still pass if the
29
+ // component set a generic name of its own and shadowed the label.
30
+ expect(input).toHaveAccessibleName('添付書類')
31
+ })
32
+
33
+ it('should be required when the label control marks it as required', async () => {
34
+ render(
35
+ <LabelControl labelText="添付書類" isRequired>
36
+ <FileInput />
37
+ </LabelControl>
38
+ )
14
39
 
15
- expect(screen.getByLabelText('File Upload')).toBeInTheDocument()
40
+ expect(screen.getByLabelText(/添付書類/)).toBeRequired()
16
41
  })
17
42
 
18
43
  it('should pass an object to the ref property', async () => {
@@ -9,4 +9,4 @@ rendering chunks...
9
9
  computing gzip size...
10
10
  dist/index.es.js 2.90 kB │ gzip: 1.00 kB
11
11
  dist/index.cjs.js 2.72 kB │ gzip: 0.99 kB
12
- ✓ built in 303ms
12
+ ✓ built in 168ms
@@ -1,12 +1,12 @@
1
1
  $ rimraf dist
2
2
  $ run-p build:*
3
3
  $ vite build
4
+ $ tsc && tsc-alias
4
5
  vite v7.3.6 building client environment for production...
5
6
  transforming...
6
- $ tsc && tsc-alias
7
7
  ✓ 365 modules transformed.
8
8
  rendering chunks...
9
9
  computing gzip size...
10
- dist/index.es.js 554.27 kB │ gzip: 141.23 kB
11
- dist/index.cjs.js 377.84 kB │ gzip: 117.18 kB
12
- ✓ built in 4.49s
10
+ dist/index.es.js 554.82 kB │ gzip: 141.39 kB
11
+ dist/index.cjs.js 378.23 kB │ gzip: 117.29 kB
12
+ ✓ built in 2.18s