@12-apps/storage 2.2.0 → 2.4.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 +2 -2
- package/src/react/create-web-storage.tsx +2 -0
- package/src/react/failures.ts +15 -2
- package/src/react/image-field.tsx +17 -3
- package/src/react/pt-BR.ts +14 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12-apps/storage",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Image uploads that land at YOUR OWN ORIGIN, never at the bucket (12-20). Isomorphic core (format allowlist, upload ceiling, object-key grammar, rendition set, refusal taxonomy, wire schemas), host-mounted backend surface (./server: createApiStorage, the local-disk driver, the image-pipeline port, the orphan reclaim), Hono adapter (./hono), the S3-compatible driver behind its own subpath (./s3) and the bound picker + upload hook (./react). Standardized adoption contract in ADOPTING.md.",
|
|
6
6
|
"exports": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@12-apps/ui": "^6.
|
|
46
|
+
"@12-apps/ui": "^6.8.0",
|
|
47
47
|
"zod": "^4.3.5"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
@@ -85,6 +85,8 @@ export function createWebStorage(config: WebStorageConfig): WebStorage {
|
|
|
85
85
|
value={imageKey}
|
|
86
86
|
onChange={setImageKey}
|
|
87
87
|
label={messages.fieldLabel}
|
|
88
|
+
removeLabel={messages.fieldRemove}
|
|
89
|
+
uploadCopy={messages.field}
|
|
88
90
|
helperText={messages.fieldHelper}
|
|
89
91
|
/>
|
|
90
92
|
</Stack>
|
package/src/react/failures.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { UploadButtonCopy } from '@12-apps/ui/copy';
|
|
2
|
+
|
|
1
3
|
import { ACCEPTED_CONTENT_TYPES } from '../content-types';
|
|
2
4
|
import { megabytes } from '../limits';
|
|
3
5
|
|
|
@@ -100,13 +102,24 @@ export interface WebStorageMessages {
|
|
|
100
102
|
/**
|
|
101
103
|
* The standalone upload page's own chrome — heading, the one-line
|
|
102
104
|
* instruction (which carries the ceiling, same rule as the refusals), the
|
|
103
|
-
* field label
|
|
104
|
-
* `createWebStorage` until copy became
|
|
105
|
+
* field label, its helper, and the button that clears a chosen image.
|
|
106
|
+
* These rendered as literals inside `createWebStorage` until copy became
|
|
107
|
+
* required config.
|
|
105
108
|
*/
|
|
106
109
|
pageTitle: string;
|
|
107
110
|
pageIntro: string;
|
|
108
111
|
fieldLabel: string;
|
|
109
112
|
fieldHelper: string;
|
|
113
|
+
fieldRemove: string;
|
|
114
|
+
/**
|
|
115
|
+
* What the dropzone ITSELF says — its hint line, its accessible name, and
|
|
116
|
+
* the three announcements only a screen reader receives. `@12-apps/ui` stopped
|
|
117
|
+
* shipping English defaults for these, so a host that answers `fieldLabel`
|
|
118
|
+
* and nothing else would have a dropzone with no name and a silent progress
|
|
119
|
+
* bar. `buttonLabel` is unused here: `ImageField` passes `fieldLabel` as the
|
|
120
|
+
* override, because the field's own label is the one a form already names.
|
|
121
|
+
*/
|
|
122
|
+
field: UploadButtonCopy;
|
|
110
123
|
}
|
|
111
124
|
|
|
112
125
|
/** Copy that only makes sense with the configured ceiling in it. */
|
|
@@ -5,6 +5,7 @@ import { Box } from '@12-apps/ui/mui/Box';
|
|
|
5
5
|
import { Stack } from '@12-apps/ui/mui/Stack';
|
|
6
6
|
import { Text } from '@12-apps/ui/typography/Text';
|
|
7
7
|
import { Button } from '@12-apps/ui/form/Button';
|
|
8
|
+
import type { UploadButtonCopy } from '@12-apps/ui/copy';
|
|
8
9
|
import { UploadButton } from '@12-apps/ui/form/UploadButton';
|
|
9
10
|
|
|
10
11
|
import { ACCEPTED_CONTENT_TYPES } from '../content-types';
|
|
@@ -34,7 +35,17 @@ export interface ImageFieldProps {
|
|
|
34
35
|
previewUrl?: string | null;
|
|
35
36
|
/** Called with the new key, or `null` when the image is removed. */
|
|
36
37
|
onChange: (imageKey: string | null) => void;
|
|
37
|
-
label
|
|
38
|
+
/** The dropzone's own label. REQUIRED — this package ships no default copy. */
|
|
39
|
+
label: string;
|
|
40
|
+
/** The button that clears a chosen image. REQUIRED, for the same reason. */
|
|
41
|
+
removeLabel: string;
|
|
42
|
+
/**
|
|
43
|
+
* What the dropzone itself says — the hint under the label, its accessible
|
|
44
|
+
* name, and the three announcements only a screen reader receives. REQUIRED:
|
|
45
|
+
* `@12-apps/ui` ships no default copy, so without this the dropzone has no
|
|
46
|
+
* name and a silent progress bar.
|
|
47
|
+
*/
|
|
48
|
+
uploadCopy: UploadButtonCopy;
|
|
38
49
|
helperText?: string;
|
|
39
50
|
/** Passed through per upload — `{ optimize: false }` for a rendered canvas. */
|
|
40
51
|
uploadOptions?: UploadOptions;
|
|
@@ -89,7 +100,10 @@ export function ImageField(props: BoundImageFieldProps): JSX.Element {
|
|
|
89
100
|
) : null}
|
|
90
101
|
<UploadButton
|
|
91
102
|
variant="dropzone"
|
|
92
|
-
|
|
103
|
+
copy={props.uploadCopy}
|
|
104
|
+
// The field's own label wins over `uploadCopy.buttonLabel`: a form
|
|
105
|
+
// already names this field, and naming it twice is how the two drift.
|
|
106
|
+
label={props.label}
|
|
93
107
|
accept={ACCEPT}
|
|
94
108
|
disabled={props.disabled || uploader.uploading}
|
|
95
109
|
uploading={uploader.uploading}
|
|
@@ -100,7 +114,7 @@ export function ImageField(props: BoundImageFieldProps): JSX.Element {
|
|
|
100
114
|
{preview ? (
|
|
101
115
|
<Box>
|
|
102
116
|
<Button variant="text" onClick={handleRemove} dataTestId={`${testId}-remove`}>
|
|
103
|
-
|
|
117
|
+
{props.removeLabel}
|
|
104
118
|
</Button>
|
|
105
119
|
</Box>
|
|
106
120
|
) : null}
|
package/src/react/pt-BR.ts
CHANGED
|
@@ -34,5 +34,19 @@ export function PT_BR_WEB_STORAGE_MESSAGES(
|
|
|
34
34
|
pageIntro: `Envie um PNG, JPG, WebP ou GIF de até ${context.limit}.`,
|
|
35
35
|
fieldLabel: 'Foto do produto',
|
|
36
36
|
fieldHelper: 'A imagem é reduzida no navegador antes do envio.',
|
|
37
|
+
fieldRemove: 'Remover imagem',
|
|
38
|
+
field: {
|
|
39
|
+
// `buttonLabel` is never read here — `ImageField` overrides it with
|
|
40
|
+
// `fieldLabel`. It is still answered, because the type is the whole of
|
|
41
|
+
// what `UploadButton` may render and a partial answer is not a pack.
|
|
42
|
+
buttonLabel: 'Foto do produto',
|
|
43
|
+
dropzoneHint: 'Solte a imagem aqui ou clique para escolher',
|
|
44
|
+
dropzoneRole: (label) => `Área de upload de imagem. ${label}`,
|
|
45
|
+
uploading: 'Enviando…',
|
|
46
|
+
dropReady: 'Imagem pronta para soltar',
|
|
47
|
+
percentUploaded: (percent) => `${percent}% enviado`,
|
|
48
|
+
uploadInProgress: (percent) => `Envio em andamento: ${percent}%`,
|
|
49
|
+
errorAnnouncement: (message) => `Erro: ${message}`,
|
|
50
|
+
},
|
|
37
51
|
};
|
|
38
52
|
}
|