@siratik/wp-component-library 0.1.1 → 0.1.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 (96) hide show
  1. package/LICENSE +5 -0
  2. package/README.md +43 -5
  3. package/components/attachment-image/README.md +118 -0
  4. package/components/attachment-image/index.js +105 -0
  5. package/components/attributes-panel/README.md +92 -0
  6. package/components/attributes-panel/index.js +324 -0
  7. package/components/badge/README.md +61 -0
  8. package/components/badge/index.js +105 -0
  9. package/components/block-appender/README.md +158 -0
  10. package/components/block-appender/index.js +135 -0
  11. package/components/block-extension/index.js +214 -0
  12. package/components/business-hours/SpecialHoursControl.js +211 -0
  13. package/components/business-hours/WeeklyHoursControl.js +419 -0
  14. package/components/business-hours/index.js +8 -0
  15. package/components/button/README.md +172 -0
  16. package/components/button/index.js +84 -0
  17. package/components/captcha-placeholder/CloudflareTurnstile.js +111 -0
  18. package/components/captcha-placeholder/GoogleRecaptcha.js +132 -0
  19. package/components/captcha-placeholder/HCaptcha.js +99 -0
  20. package/components/captcha-placeholder/README.md +228 -0
  21. package/components/captcha-placeholder/index.js +39 -0
  22. package/components/captcha-placeholder/styles.js +33 -0
  23. package/components/geocoder/AddressEntryControl.js +390 -0
  24. package/components/geocoder/GeocoderSearchControl.js +353 -0
  25. package/components/geocoder/countryOptions.js +66 -0
  26. package/components/geocoder/geocoder.js +400 -0
  27. package/components/geocoder/index.js +16 -0
  28. package/components/icon-picker/Icon.js +53 -0
  29. package/components/icon-picker/IconPicker.js +70 -0
  30. package/components/icon-picker/IconPickerModal.js +474 -0
  31. package/components/icon-picker/IconPickerToolbarButton.js +60 -0
  32. package/components/icon-picker/InlineIconPicker.js +92 -0
  33. package/components/icon-picker/api.js +181 -0
  34. package/components/icon-picker/config-bootstrap.js +108 -0
  35. package/components/icon-picker/hooks.js +157 -0
  36. package/components/icon-picker/index.js +39 -0
  37. package/components/icon-picker/load-script.js +33 -0
  38. package/components/icon-picker/loaders.js +79 -0
  39. package/components/icon-picker/store.js +223 -0
  40. package/components/icon-picker/styles.js +232 -0
  41. package/components/icon-picker/utils.js +138 -0
  42. package/components/layout/README.md +268 -0
  43. package/components/link-tools-panel/README.md +49 -0
  44. package/components/link-tools-panel/index.js +198 -0
  45. package/components/link-tools-panel/styles.js +90 -0
  46. package/components/media/README.md +288 -0
  47. package/components/media/SettingsMediaUpload.js +187 -0
  48. package/components/media/editor-media-upload.js +65 -0
  49. package/components/media/image-controls.js +196 -0
  50. package/components/media/index.js +13 -0
  51. package/components/media/inspector-media-upload.js +290 -0
  52. package/components/media/toolbar-media-upload.js +53 -0
  53. package/components/media/utils/aspect-ratios.js +118 -0
  54. package/components/meta/MetaPanel.js +75 -0
  55. package/components/meta/README.md +46 -0
  56. package/components/meta/index.js +6 -0
  57. package/components/meta/meta-gated-editor.js +282 -0
  58. package/components/query/README.md +340 -0
  59. package/components/query/cardTemplatePartPanel.js +69 -0
  60. package/components/query/cardTemplatePartSelect.js +165 -0
  61. package/components/query/cardTemplatePartUtils.js +119 -0
  62. package/components/query/columnCountControl.js +63 -0
  63. package/components/query/displayTypeSelect.js +52 -0
  64. package/components/query/examples.js +166 -0
  65. package/components/query/hideCurrentPostControl.js +47 -0
  66. package/components/query/index.js +20 -0
  67. package/components/query/manualPostSelector.js +125 -0
  68. package/components/query/manualTermSelector.js +141 -0
  69. package/components/query/orderBySelect.js +95 -0
  70. package/components/query/postTypeSelect.js +67 -0
  71. package/components/query/postsPerPageControl.js +51 -0
  72. package/components/query/selectionModeControl.js +61 -0
  73. package/components/query/taxonomySelect.js +139 -0
  74. package/components/query/utils.js +75 -0
  75. package/components/repeater/README.md +159 -0
  76. package/components/repeater/index.js +829 -0
  77. package/components/segmented-bar/README.md +30 -0
  78. package/components/segmented-bar/index.js +68 -0
  79. package/components/sortable-select/README.md +153 -0
  80. package/components/sortable-select/custom-sortable-token.js +127 -0
  81. package/components/sortable-select/index.js +693 -0
  82. package/components/style-picker/README.md +36 -0
  83. package/components/style-picker/index.js +92 -0
  84. package/components/variable-field/README.md +299 -0
  85. package/components/variable-field/index.js +592 -0
  86. package/components/variable-field/value-to-chip-html.js +38 -0
  87. package/components/variable-inserter/README.md +68 -0
  88. package/components/variable-inserter/index.js +168 -0
  89. package/constants/statusColors.js +1 -1
  90. package/editor.js +16 -0
  91. package/index.js +127 -0
  92. package/package.json +21 -13
  93. package/utils/kitaris-localize.js +128 -0
  94. package/utils/slug-aware-color-setter.js +27 -0
  95. package/build/index.asset.php +0 -20
  96. package/build/index.js +0 -1242
@@ -0,0 +1,288 @@
1
+ # Media Components
2
+
3
+ A comprehensive set of media upload and management components for WordPress blocks, providing different UI patterns for various contexts within the block editor.
4
+
5
+ ## Components
6
+
7
+ ### ToolbarMediaUpload
8
+ Media upload button for block toolbars with customizable icons and labels.
9
+
10
+ ### EditorMediaUpload
11
+ Flexible media upload component for the main editor canvas with image preview support.
12
+
13
+ ### InspectorMediaUpload
14
+ Media upload control for inspector panels with integrated preview and management.
15
+
16
+ ### SettingsMediaUpload
17
+ Advanced media upload for settings panels with focal point control and additional options.
18
+
19
+ ### ImageControls
20
+ Comprehensive image control panel with aspect ratio, object fit, and focal point settings.
21
+
22
+ ## Usage
23
+
24
+ ```jsx
25
+ import {
26
+ ToolbarMediaUpload,
27
+ EditorMediaUpload,
28
+ InspectorMediaUpload,
29
+ SettingsMediaUpload,
30
+ ImageControls
31
+ } from '@siratik/wp-component-library/components/media';
32
+
33
+ // Toolbar upload
34
+ <BlockControls>
35
+ <ToolbarMediaUpload
36
+ buttonTitle="Select Image"
37
+ onSelect={handleImageSelect}
38
+ allowedTypes={['image']}
39
+ value={imageId}
40
+ />
41
+ </BlockControls>
42
+
43
+ // Editor canvas upload
44
+ <EditorMediaUpload
45
+ buttonTitle="Choose Background"
46
+ onSelect={handleImageSelect}
47
+ imageUrl={backgroundUrl}
48
+ imageAlt={backgroundAlt}
49
+ />
50
+
51
+ // Inspector panel upload
52
+ <InspectorControls>
53
+ <InspectorMediaUpload
54
+ buttonTitle="Upload Logo"
55
+ onSelect={handleLogoSelect}
56
+ onRemove={handleLogoRemove}
57
+ imageId={logoId}
58
+ imageUrl={logoUrl}
59
+ />
60
+ </InspectorControls>
61
+
62
+ // Advanced settings upload
63
+ <SettingsMediaUpload
64
+ label="Hero Image"
65
+ onSelect={handleHeroSelect}
66
+ onRemove={handleHeroRemove}
67
+ value={heroImage}
68
+ focalPoint={focalPoint}
69
+ onFocalPointChange={setFocalPoint}
70
+ />
71
+ ```
72
+
73
+ ## Common Props
74
+
75
+ ### Core Props (All Components)
76
+ | Prop | Type | Default | Description |
77
+ |------|------|---------|-------------|
78
+ | `onSelect` | `function` | Required | Media selection handler |
79
+ | `allowedTypes` | `array` | `['image']` | Allowed media types |
80
+ | `buttonTitle` | `string` | Varies | Button label text |
81
+
82
+ ### ToolbarMediaUpload Props
83
+ | Prop | Type | Default | Description |
84
+ |------|------|---------|-------------|
85
+ | `value` | `number` | - | Selected media ID |
86
+ | `buttonIcon` | `element` | `image` | Toolbar button icon |
87
+ | `buttonLabel` | `string` | - | Accessibility label |
88
+ | `multiple` | `boolean` | `false` | Allow multiple selection |
89
+ | `gallery` | `boolean` | `false` | Gallery mode |
90
+
91
+ ### EditorMediaUpload Props
92
+ | Prop | Type | Default | Description |
93
+ |------|------|---------|-------------|
94
+ | `imageUrl` | `string` | - | Current image URL for preview |
95
+ | `imageAlt` | `string` | - | Image alt text |
96
+ | `imageId` | `number` | - | Current image ID |
97
+ | `onRemove` | `function` | - | Image removal handler |
98
+ | `className` | `string` | - | Additional CSS classes |
99
+
100
+ ### InspectorMediaUpload Props
101
+ | Prop | Type | Default | Description |
102
+ |------|------|---------|-------------|
103
+ | `imageId` | `number` | - | Current image ID |
104
+ | `imageUrl` | `string` | - | Current image URL |
105
+ | `onRemove` | `function` | - | Image removal handler |
106
+ | `label` | `string` | - | Control label |
107
+ | `help` | `string` | - | Help text |
108
+
109
+ ### SettingsMediaUpload Props
110
+ | Prop | Type | Default | Description |
111
+ |------|------|---------|-------------|
112
+ | `label` | `string` | `"Image"` | Control label |
113
+ | `value` | `object` | - | Image data object |
114
+ | `onRemove` | `function` | - | Image removal handler |
115
+ | `focalPoint` | `object` | - | Focal point coordinates |
116
+ | `onFocalPointChange` | `function` | - | Focal point change handler |
117
+ | `help` | `string` | - | Help text |
118
+
119
+ ## ImageControls Component
120
+
121
+ Advanced image settings panel with comprehensive controls:
122
+
123
+ ```jsx
124
+ <ImageControls
125
+ imageId={imageId}
126
+ imageUrl={imageUrl}
127
+ onRemove={handleRemove}
128
+ aspectRatio={aspectRatio}
129
+ onAspectRatioChange={setAspectRatio}
130
+ objectFit={objectFit}
131
+ onObjectFitChange={setObjectFit}
132
+ focalPoint={focalPoint}
133
+ onFocalPointChange={setFocalPoint}
134
+ imagePosition={imagePosition}
135
+ onImagePositionChange={setImagePosition}
136
+ />
137
+ ```
138
+
139
+ ### ImageControls Props
140
+ | Prop | Type | Description |
141
+ |------|------|-------------|
142
+ | `imageId` | `number` | Current image ID |
143
+ | `imageUrl` | `string` | Current image URL |
144
+ | `onRemove` | `function` | Image removal handler |
145
+ | `aspectRatio` | `string` | Aspect ratio value |
146
+ | `onAspectRatioChange` | `function` | Aspect ratio change handler |
147
+ | `objectFit` | `string` | Object fit value (cover, contain, etc.) |
148
+ | `onObjectFitChange` | `function` | Object fit change handler |
149
+ | `focalPoint` | `object` | Focal point {x, y} coordinates |
150
+ | `onFocalPointChange` | `function` | Focal point change handler |
151
+ | `imagePosition` | `string` | CSS background position |
152
+ | `onImagePositionChange` | `function` | Position change handler |
153
+
154
+ ## Aspect Ratios
155
+
156
+ The library includes predefined aspect ratios via `ASPECT_RATIOS`:
157
+
158
+ ```jsx
159
+ import { ASPECT_RATIOS } from '@siratik/wp-component-library/components/media/utils/aspect-ratios';
160
+
161
+ // Available ratios:
162
+ {
163
+ 'original': 'Original',
164
+ '1-1': 'Square (1:1)',
165
+ '4-3': 'Standard (4:3)',
166
+ '16-9': 'Widescreen (16:9)',
167
+ '21-9': 'Ultrawide (21:9)',
168
+ '3-2': 'Classic (3:2)',
169
+ '5-4': 'Large Format (5:4)',
170
+ '9-16': 'Portrait (9:16)'
171
+ }
172
+ ```
173
+
174
+ ## Examples
175
+
176
+ ### Hero Section with Background
177
+ ```jsx
178
+ function HeroSection({ attributes, setAttributes }) {
179
+ const { backgroundImage, focalPoint } = attributes;
180
+
181
+ return (
182
+ <>
183
+ <InspectorControls>
184
+ <PanelBody title="Background">
185
+ <SettingsMediaUpload
186
+ label="Background Image"
187
+ value={backgroundImage}
188
+ onSelect={(media) => setAttributes({
189
+ backgroundImage: {
190
+ id: media.id,
191
+ url: media.url,
192
+ alt: media.alt
193
+ }
194
+ })}
195
+ onRemove={() => setAttributes({ backgroundImage: null })}
196
+ focalPoint={focalPoint}
197
+ onFocalPointChange={(point) => setAttributes({ focalPoint: point })}
198
+ />
199
+ </PanelBody>
200
+ </InspectorControls>
201
+
202
+ <div
203
+ className="hero"
204
+ style={{
205
+ backgroundImage: `url(${backgroundImage?.url})`,
206
+ backgroundPosition: `${focalPoint?.x * 100}% ${focalPoint?.y * 100}%`
207
+ }}
208
+ >
209
+ {/* Hero content */}
210
+ </div>
211
+ </>
212
+ );
213
+ }
214
+ ```
215
+
216
+ ### Gallery Block
217
+ ```jsx
218
+ function GalleryBlock({ attributes, setAttributes }) {
219
+ const { images } = attributes;
220
+
221
+ return (
222
+ <BlockControls>
223
+ <ToolbarMediaUpload
224
+ buttonTitle="Add Images"
225
+ buttonIcon={gallery}
226
+ onSelect={(media) => {
227
+ const newImages = media.map(item => ({
228
+ id: item.id,
229
+ url: item.url,
230
+ alt: item.alt
231
+ }));
232
+ setAttributes({ images: [...images, ...newImages] });
233
+ }}
234
+ multiple={true}
235
+ gallery={true}
236
+ allowedTypes={['image']}
237
+ />
238
+ </BlockControls>
239
+ );
240
+ }
241
+ ```
242
+
243
+ ### Card with Featured Image
244
+ ```jsx
245
+ function Card({ attributes, setAttributes }) {
246
+ const { featuredImage, aspectRatio, objectFit } = attributes;
247
+
248
+ return (
249
+ <InspectorControls>
250
+ <PanelBody title="Featured Image">
251
+ <ImageControls
252
+ imageId={featuredImage?.id}
253
+ imageUrl={featuredImage?.url}
254
+ onRemove={() => setAttributes({ featuredImage: null })}
255
+ aspectRatio={aspectRatio}
256
+ onAspectRatioChange={(ratio) => setAttributes({ aspectRatio: ratio })}
257
+ objectFit={objectFit}
258
+ onObjectFitChange={(fit) => setAttributes({ objectFit: fit })}
259
+ />
260
+ </PanelBody>
261
+ </InspectorControls>
262
+ );
263
+ }
264
+ ```
265
+
266
+ ## Media Selection Handler
267
+
268
+ Standard media selection handler pattern:
269
+ ```jsx
270
+ const handleMediaSelect = (media) => {
271
+ setAttributes({
272
+ imageId: media.id,
273
+ imageUrl: media.url,
274
+ imageAlt: media.alt,
275
+ imageWidth: media.width,
276
+ imageHeight: media.height
277
+ });
278
+ };
279
+ ```
280
+
281
+ ## Notes
282
+
283
+ - All components integrate with WordPress MediaUpload
284
+ - Components handle both selection and removal of media
285
+ - Focal point control uses WordPress FocalPointPicker
286
+ - Image preview automatically displayed when URL provided
287
+ - Components styled to match WordPress admin UI
288
+ - Supports all WordPress media types via allowedTypes prop
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Settings Media Upload Component
3
+ * Designed for admin settings contexts (not block editor)
4
+ */
5
+ import { MediaUpload, MediaUploadCheck } from "@wordpress/media-utils";
6
+ import { Button, Flex, Placeholder } from "@wordpress/components";
7
+ import { useSelect } from "@wordpress/data";
8
+ import { __ } from "@wordpress/i18n";
9
+ import styled from '@emotion/styled';
10
+
11
+ const ALLOWED_MEDIA_TYPES = ["image"];
12
+
13
+ // Styled components
14
+ const StyledSettingsMediaUpload = styled.div`
15
+ &__header {
16
+ margin-bottom: 12px;
17
+ }
18
+ `;
19
+
20
+ const StyledLabel = styled.h4`
21
+ margin: 0 0 4px 0;
22
+ font-size: 13px;
23
+ font-weight: 600;
24
+ color: #1e1e1e;
25
+ `;
26
+
27
+ const StyledHelp = styled.p`
28
+ margin: 0;
29
+ font-size: 13px;
30
+ color: #757575;
31
+ line-height: 1.4;
32
+ `;
33
+
34
+ const StyledPreview = styled.div`
35
+ margin-bottom: 12px;
36
+ border: 1px solid #ddd;
37
+ border-radius: 4px;
38
+ overflow: hidden;
39
+ background: #f9f9f9;
40
+ `;
41
+
42
+ const StyledImage = styled.img`
43
+ max-width: 100%;
44
+ height: auto;
45
+ display: block;
46
+ max-height: 200px;
47
+ object-fit: cover;
48
+ `;
49
+
50
+ const StyledPlaceholder = styled(Placeholder)`
51
+ min-height: 120px;
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+
56
+ .components-placeholder__label {
57
+ font-size: 13px;
58
+ color: #757575;
59
+ }
60
+
61
+ .components-placeholder__icon {
62
+ margin-bottom: 8px;
63
+ opacity: 0.3;
64
+ }
65
+ `;
66
+
67
+ const StyledButtons = styled.div`
68
+ .components-flex {
69
+ align-items: center;
70
+ }
71
+
72
+ .components-button {
73
+ min-width: 100px;
74
+ }
75
+ `;
76
+
77
+ /**
78
+ * Settings Media Upload
79
+ *
80
+ * @param {object} props
81
+ * @param {number|null} props.imageId - The ID of the selected image
82
+ * @param {Function} props.onSelect - Callback when image is selected
83
+ * @param {Function} props.onRemove - Callback when image is removed
84
+ * @param {string} props.label - Label for the control
85
+ * @param {string} props.help - Help text for the control
86
+ * @param {string} props.buttonTitle - Custom button text
87
+ * @param {boolean} props.showImagePlaceholder - Whether to show image preview
88
+ * @param {string} props.size - Image size for preview (default: 'medium')
89
+ * @returns {JSX.Element}
90
+ */
91
+ function SettingsMediaUpload({
92
+ imageId,
93
+ onSelect,
94
+ onRemove,
95
+ label = null,
96
+ help = null,
97
+ buttonTitle = null,
98
+ showImagePlaceholder = true,
99
+ }) {
100
+ // Get image data for preview
101
+ const imageData = useSelect(
102
+ (select) => {
103
+ if (!imageId) { return null; }
104
+ return select("core").getEntityRecord("postType", "attachment", imageId);
105
+ },
106
+ [imageId]
107
+ );
108
+
109
+ const hasImage = !!imageId;
110
+
111
+ return (
112
+ <StyledSettingsMediaUpload>
113
+ {/* Label and Help */}
114
+ {(label || help) && (
115
+ <div className="settings-media-upload__header">
116
+ {label && (
117
+ <StyledLabel>
118
+ {label}
119
+ </StyledLabel>
120
+ )}
121
+ {help && (
122
+ <StyledHelp>
123
+ {help}
124
+ </StyledHelp>
125
+ )}
126
+ </div>
127
+ )}
128
+
129
+ {/* Image Preview or Placeholder */}
130
+ {showImagePlaceholder && (
131
+ <StyledPreview>
132
+ {hasImage && imageData ? (
133
+ <StyledImage
134
+ src={imageData.source_url}
135
+ alt={imageData.alt_text || "Selected image"}
136
+ />
137
+ ) : (
138
+ <StyledPlaceholder
139
+ icon="format-image"
140
+ label={__("No image selected", "wp-component-library")}
141
+ />
142
+ )}
143
+ </StyledPreview>
144
+ )}
145
+
146
+ {/* Buttons */}
147
+ <StyledButtons>
148
+ <MediaUploadCheck>
149
+ <Flex gap={2}>
150
+ <MediaUpload
151
+ onSelect={onSelect}
152
+ allowedTypes={ALLOWED_MEDIA_TYPES}
153
+ value={imageId}
154
+ render={({ open }) => (
155
+ <Button
156
+ variant="secondary"
157
+ onClick={open}
158
+ size="default"
159
+ >
160
+ {buttonTitle ||
161
+ (hasImage
162
+ ? __("Change Image", "wp-component-library")
163
+ : __("Upload Image", "wp-component-library")
164
+ )
165
+ }
166
+ </Button>
167
+ )}
168
+ />
169
+
170
+ {hasImage && (
171
+ <Button
172
+ variant="secondary"
173
+ isDestructive={true}
174
+ onClick={onRemove}
175
+ size="default"
176
+ >
177
+ {__("Remove Image", "wp-component-library")}
178
+ </Button>
179
+ )}
180
+ </Flex>
181
+ </MediaUploadCheck>
182
+ </StyledButtons>
183
+ </StyledSettingsMediaUpload>
184
+ );
185
+ }
186
+
187
+ export { SettingsMediaUpload };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Editor Media Upload Component
3
+ */
4
+ import { MediaUpload, MediaUploadCheck } from "@wordpress/block-editor";
5
+ import { Button, Placeholder } from "@wordpress/components";
6
+ import { upload } from "@wordpress/icons";
7
+
8
+ const ALLOWED_MEDIA_TYPES = ["image"];
9
+
10
+ /**
11
+ * Editor Media Upload
12
+ *
13
+ * @param {object} props
14
+ * @returns {JSX.Element}
15
+ */
16
+ function EditorMediaUpload({
17
+ mediaIDs,
18
+ onSelect,
19
+ gallery,
20
+ multiple,
21
+ buttonTitle,
22
+ style,
23
+ }) {
24
+ // Handle both ID and object formats for mediaIDs
25
+ const getMediaId = (mediaData) => {
26
+ if (!mediaData) { return null; }
27
+ if (typeof mediaData === "number") { return mediaData; }
28
+ if (typeof mediaData === "object" && mediaData.id) { return mediaData.id; }
29
+ return null;
30
+ };
31
+
32
+ const mediaId = getMediaId(mediaIDs);
33
+
34
+ return (
35
+ <Placeholder
36
+ style={style}
37
+ withIllustration={true}
38
+ className="placeholder-image placeholder-image--built"
39
+ >
40
+ <MediaUploadCheck>
41
+ <MediaUpload
42
+ onSelect={onSelect}
43
+ allowedTypes={ALLOWED_MEDIA_TYPES}
44
+ value={mediaId}
45
+ render={({ open }) => (
46
+ <Button
47
+ icon={upload}
48
+ variant="primary"
49
+ label="Upload or Select Image(s)"
50
+ showTooltip
51
+ tooltipPosition="top center"
52
+ onClick={open}
53
+ >
54
+ {buttonTitle}
55
+ </Button>
56
+ )}
57
+ gallery={gallery}
58
+ multiple={multiple}
59
+ />
60
+ </MediaUploadCheck>
61
+ </Placeholder>
62
+ );
63
+ }
64
+
65
+ export { EditorMediaUpload };