@inglorious/ui 8.5.0 → 8.6.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,6 @@
1
1
  {
2
2
  "name": "@inglorious/ui",
3
- "version": "8.5.0",
3
+ "version": "8.6.0",
4
4
  "description": "A design system for Inglorious Web with render-function components and customizable themes",
5
5
  "author": "Matteo Antony Mistretta <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
6
  "license": "MIT",
@@ -57,7 +57,19 @@ export default {
57
57
  options: ["button", "submit", "reset", "menu"],
58
58
  description: "Native HTML button type attribute.",
59
59
  },
60
+ accept: {
61
+ control: "text",
62
+ description: "File types the picker offers (with `onFileSelect`).",
63
+ },
64
+ isMultiple: {
65
+ control: "boolean",
66
+ description: "Lets the picker select more than one file.",
67
+ },
60
68
  onClick: { action: "onClick" },
69
+ onFileSelect: {
70
+ action: "onFileSelect",
71
+ description: "Turns the button into a file picker.",
72
+ },
61
73
  },
62
74
  parameters: {
63
75
  docs: {
@@ -150,6 +162,16 @@ Round.args = {
150
162
  children: "+",
151
163
  }
152
164
 
165
+ export const FilePicker = {}
166
+ FilePicker.args = {
167
+ ...Default.args,
168
+ children: "Change photo",
169
+ variant: "outline",
170
+ shape: "pill",
171
+ accept: "image/jpeg,image/png,image/webp",
172
+ onFileSelect: () => {},
173
+ }
174
+
153
175
  export const CustomContent = {}
154
176
  CustomContent.args = {
155
177
  ...Default.args,
@@ -3,7 +3,7 @@
3
3
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
4
4
  */
5
5
 
6
- import { html } from "@inglorious/web"
6
+ import { html, nothing } from "@inglorious/web"
7
7
  import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
 
@@ -12,10 +12,14 @@ import { applyElementProps } from "../../shared/apply-element-props.js"
12
12
  /**
13
13
  * Renders a themed button for actions and form submission.
14
14
  * Supports variants, sizes, shapes, pressed state, and full-width layout.
15
+ * With `onFileSelect`, the button also opens a file picker on click.
15
16
  * @example
16
17
  * // Stateless usage
17
18
  * button.render({ children: 'Click me', variant: 'primary' })
18
19
  *
20
+ * // File picker
21
+ * button.render({ children: 'Upload', accept: 'image/*', onFileSelect })
22
+ *
19
23
  * @param {ButtonProps} props
20
24
  * @returns {TemplateResult}
21
25
  */
@@ -34,7 +38,10 @@ export function render(props) {
34
38
  ariaLabel = "",
35
39
  isAriaPressed = false,
36
40
  className = "",
41
+ accept,
42
+ isMultiple = false,
37
43
  onClick,
44
+ onFileSelect,
38
45
  ...rest
39
46
  } = props
40
47
 
@@ -57,6 +64,13 @@ export function render(props) {
57
64
  ...extraClasses,
58
65
  }
59
66
 
67
+ const handleClick = onFileSelect
68
+ ? (event) => {
69
+ onClick?.(event)
70
+ event.currentTarget.nextElementSibling.click()
71
+ }
72
+ : onClick
73
+
60
74
  return html`
61
75
  <button
62
76
  type=${buttonType}
@@ -64,10 +78,29 @@ export function render(props) {
64
78
  aria-pressed=${isAriaPressed}
65
79
  class=${classMap(classes)}
66
80
  ?disabled=${isDisabled}
67
- @click=${onClick}
81
+ @click=${handleClick}
68
82
  ${ref((element) => applyElementProps(element, rest))}
69
83
  >
70
84
  ${children}
71
85
  </button>
86
+ ${
87
+ onFileSelect
88
+ ? html`<input
89
+ type="file"
90
+ accept=${accept ?? ""}
91
+ ?multiple=${isMultiple}
92
+ ?disabled=${isDisabled}
93
+ hidden
94
+ @change=${(event) => handleFileChange(event, onFileSelect)}
95
+ />`
96
+ : nothing
97
+ }
72
98
  `
73
99
  }
100
+
101
+ function handleFileChange(event, onFileSelect) {
102
+ const { files } = event.target
103
+ if (files?.length) onFileSelect(files)
104
+ // Clear the input so picking the same file again still fires `change`
105
+ event.target.value = ""
106
+ }
@@ -58,6 +58,10 @@
58
58
  inset: 0;
59
59
  opacity: 0;
60
60
  cursor: pointer;
61
+
62
+ &::file-selector-button {
63
+ cursor: inherit;
64
+ }
61
65
  }
62
66
 
63
67
  .iw-upload-content {
@@ -22,7 +22,13 @@ export interface ButtonProps {
22
22
  ariaLabel?: string
23
23
  isAriaPressed?: boolean
24
24
  className?: string
25
- onClick?: () => void
25
+ /** File types the picker offers, as in the native `accept` attribute */
26
+ accept?: string
27
+ /** Lets the picker select more than one file */
28
+ isMultiple?: boolean
29
+ onClick?: (event: MouseEvent) => void
30
+ /** Turns the button into a file picker; called with the chosen files */
31
+ onFileSelect?: (files: FileList) => void
26
32
  [key: string]: unknown
27
33
  }
28
34