@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,92 @@
1
+ /**
2
+ * StylePicker Component
3
+ *
4
+ * One option out of a few, shown like core's block Styles panel: a two-column
5
+ * grid of buttons, the chosen one filled. For a block setting that reads as a
6
+ * style but isn't a block style (an attribute such as a button variant).
7
+ *
8
+ * It renders core's own markup and classes (block-editor-block-styles__*), so
9
+ * the block editor's styles apply and it matches the Styles panel exactly.
10
+ *
11
+ * @package WPComponentLibrary
12
+ */
13
+
14
+ import {
15
+ BaseControl,
16
+ Button,
17
+ __experimentalTruncate as Truncate,
18
+ } from "@wordpress/components";
19
+ import { useId } from "@wordpress/element";
20
+
21
+ /**
22
+ * @param {Object} props
23
+ * @param {string} props.label Control label.
24
+ * @param {string} [props.help] Help text.
25
+ * @param {string} props.value The chosen option's value.
26
+ * @param {Array<{value: string, label: string}>} props.options Options, in order.
27
+ * @param {Function} props.onChange Receives the chosen value.
28
+ * @param {boolean} [props.hideLabelFromVision] Keep the label for screen readers only.
29
+ * @param {string} [props.className]
30
+ * @return {WPElement} The picker.
31
+ */
32
+ export function StylePicker({
33
+ label,
34
+ help,
35
+ value,
36
+ options,
37
+ onChange,
38
+ hideLabelFromVision = false,
39
+ className,
40
+ }) {
41
+ const labelId = useId();
42
+
43
+ return (
44
+ <BaseControl
45
+ __nextHasNoMarginBottom
46
+ help={help}
47
+ className={className}
48
+ >
49
+ {hideLabelFromVision ? (
50
+ <span id={labelId} className="screen-reader-text">
51
+ {label}
52
+ </span>
53
+ ) : (
54
+ <BaseControl.VisualLabel>
55
+ <span id={labelId}>{label}</span>
56
+ </BaseControl.VisualLabel>
57
+ )}
58
+ <div
59
+ className="block-editor-block-styles"
60
+ role="group"
61
+ aria-labelledby={labelId}
62
+ >
63
+ <div className="block-editor-block-styles__variants">
64
+ {options.map((option) => {
65
+ const isActive = option.value === value;
66
+
67
+ return (
68
+ <Button
69
+ key={option.value}
70
+ __next40pxDefaultSize
71
+ variant="secondary"
72
+ className={`block-editor-block-styles__item${
73
+ isActive ? " is-active" : ""
74
+ }`}
75
+ label={option.label}
76
+ aria-current={isActive}
77
+ onClick={() => onChange(option.value)}
78
+ >
79
+ <Truncate
80
+ numberOfLines={1}
81
+ className="block-editor-block-styles__item-text"
82
+ >
83
+ {option.label}
84
+ </Truncate>
85
+ </Button>
86
+ );
87
+ })}
88
+ </div>
89
+ </div>
90
+ </BaseControl>
91
+ );
92
+ }
@@ -0,0 +1,299 @@
1
+ # VariableField Component
2
+
3
+ An advanced input field component with autocomplete functionality for inserting variables using the @ symbol trigger. Perfect for template fields, email composers, or any input that needs variable interpolation.
4
+
5
+ ## Features
6
+
7
+ - **@ Symbol Triggered Autocomplete** - Type @ to show variable suggestions
8
+ - **Smart Filtering** - Real-time filtering as you type after @
9
+ - **Keyboard Navigation** - Full keyboard support with arrow keys, Enter, and Escape
10
+ - **Mouse Support** - Click to select, hover to highlight
11
+ - **Cursor-Aware Replacement** - Replaces text at cursor position precisely
12
+ - **Flexible Input Types** - Supports both text input and textarea
13
+ - **Customizable Options** - Define your own variable structure
14
+ - **Accessibility** - Screen reader compatible with proper ARIA attributes
15
+ - **Click Outside Detection** - Automatically closes suggestions when clicking elsewhere
16
+ - **Ref Forwarding** - Exposes focus method to parent components
17
+
18
+ ## Usage
19
+
20
+ ```jsx
21
+ import { VariableField } from '@siratik/wp-component-library/components/variable-field';
22
+
23
+ // Basic usage with simple options
24
+ <VariableField
25
+ value={content}
26
+ onChange={setContent}
27
+ options={[
28
+ { label: 'User Name', value: '{user_name}' },
29
+ { label: 'User Email', value: '{user_email}' },
30
+ { label: 'Current Date', value: '{date}' },
31
+ { label: 'Site Title', value: '{site_title}' }
32
+ ]}
33
+ placeholder="Type @ to insert variables"
34
+ />
35
+
36
+ // With custom option structure
37
+ <VariableField
38
+ value={template}
39
+ onChange={setTemplate}
40
+ options={customVariables}
41
+ getOptionLabel={(option) => option.displayName}
42
+ getOptionValue={(option) => option.code}
43
+ label="Email Template"
44
+ help="Use @ to insert merge tags"
45
+ />
46
+
47
+ // As textarea with advanced options
48
+ <VariableField
49
+ value={message}
50
+ onChange={setMessage}
51
+ options={messageVariables}
52
+ inputType="textarea"
53
+ label="Message Body"
54
+ placeholder="Compose your message. Type @ for variables."
55
+ className="message-composer"
56
+ />
57
+ ```
58
+
59
+ ## Props
60
+
61
+ | Prop | Type | Default | Description |
62
+ |------|------|---------|-------------|
63
+ | `value` | `string` | `""` | Current input value |
64
+ | `onChange` | `function` | Required | Value change handler |
65
+ | `options` | `array` | `[]` | Available variables for autocomplete |
66
+ | `getOptionLabel` | `function` | `(opt) => opt.label` | Extract display label from option |
67
+ | `getOptionValue` | `function` | `(opt) => opt.value` | Extract value from option |
68
+ | `placeholder` | `string` | - | Input placeholder text |
69
+ | `label` | `string` | - | Field label |
70
+ | `help` | `string` | - | Help text displayed below input |
71
+ | `isDisabled` | `boolean` | `false` | Disable the input |
72
+ | `inputType` | `string` | `"text"` | Input type: "text" or "textarea" |
73
+ | `className` | `string` | - | Additional CSS classes |
74
+
75
+ ## Option Structure
76
+
77
+ Options can be simple or complex objects:
78
+
79
+ ### Simple Structure
80
+ ```jsx
81
+ const simpleOptions = [
82
+ { label: 'First Name', value: '{first_name}' },
83
+ { label: 'Last Name', value: '{last_name}' }
84
+ ];
85
+ ```
86
+
87
+ ### Custom Structure
88
+ ```jsx
89
+ const customOptions = [
90
+ {
91
+ displayName: 'Customer Name',
92
+ code: '{{customer.name}}',
93
+ category: 'Customer Data',
94
+ description: 'Full name of the customer'
95
+ }
96
+ ];
97
+
98
+ // With custom getters
99
+ <VariableField
100
+ options={customOptions}
101
+ getOptionLabel={(opt) => opt.displayName}
102
+ getOptionValue={(opt) => opt.code}
103
+ />
104
+ ```
105
+
106
+ ## Autocomplete Behavior
107
+
108
+ 1. **Trigger** - Type @ anywhere in the input
109
+ 2. **Filter** - Continue typing to filter suggestions
110
+ 3. **Navigate** - Use ↑↓ arrow keys or mouse
111
+ 4. **Select** - Press Enter or click to insert
112
+ 5. **Cancel** - Press Escape or click outside
113
+
114
+ The selected variable replaces the @word at the cursor position.
115
+
116
+ ## Keyboard Shortcuts
117
+
118
+ | Key | Action |
119
+ |-----|--------|
120
+ | `@` | Open autocomplete suggestions |
121
+ | `↑` `↓` | Navigate through suggestions |
122
+ | `Enter` | Select highlighted suggestion |
123
+ | `Escape` | Close suggestions |
124
+ | `Tab` | Close suggestions and move focus |
125
+
126
+ ## Examples
127
+
128
+ ### Email Template Builder
129
+ ```jsx
130
+ function EmailTemplateBuilder() {
131
+ const [subject, setSubject] = useState('');
132
+ const [body, setBody] = useState('');
133
+
134
+ const emailVariables = [
135
+ { label: 'Recipient Name', value: '{{recipient.name}}' },
136
+ { label: 'Recipient Email', value: '{{recipient.email}}' },
137
+ { label: 'Sender Name', value: '{{sender.name}}' },
138
+ { label: 'Company Name', value: '{{company.name}}' },
139
+ { label: 'Unsubscribe Link', value: '{{unsubscribe_url}}' },
140
+ { label: 'Current Year', value: '{{current_year}}' }
141
+ ];
142
+
143
+ return (
144
+ <div>
145
+ <VariableField
146
+ label="Subject Line"
147
+ value={subject}
148
+ onChange={setSubject}
149
+ options={emailVariables}
150
+ placeholder="Email subject..."
151
+ />
152
+
153
+ <VariableField
154
+ label="Email Body"
155
+ value={body}
156
+ onChange={setBody}
157
+ options={emailVariables}
158
+ inputType="textarea"
159
+ placeholder="Compose your email. Type @ to add variables."
160
+ help="Variables will be replaced with actual values when sending"
161
+ />
162
+ </div>
163
+ );
164
+ }
165
+ ```
166
+
167
+ ### Dynamic Form Field
168
+ ```jsx
169
+ function DynamicFormField() {
170
+ const [formula, setFormula] = useState('');
171
+
172
+ const fieldVariables = [
173
+ { label: 'Field A', value: '[field_a]' },
174
+ { label: 'Field B', value: '[field_b]' },
175
+ { label: 'Total', value: '[total]' },
176
+ { label: 'Tax Rate', value: '[tax_rate]' },
177
+ { label: 'Subtotal', value: '[subtotal]' }
178
+ ];
179
+
180
+ return (
181
+ <VariableField
182
+ label="Calculation Formula"
183
+ value={formula}
184
+ onChange={setFormula}
185
+ options={fieldVariables}
186
+ placeholder="e.g., [field_a] + [field_b] * [tax_rate]"
187
+ help="Create formulas using @ to reference other fields"
188
+ />
189
+ );
190
+ }
191
+ ```
192
+
193
+ ### Chat Message Composer
194
+ ```jsx
195
+ function ChatComposer() {
196
+ const messageRef = useRef();
197
+ const [message, setMessage] = useState('');
198
+
199
+ const quickResponses = [
200
+ { label: 'Greeting', value: 'Hello! How can I help you today?' },
201
+ { label: 'Thank You', value: 'Thank you for contacting us!' },
202
+ { label: 'Agent Name', value: '{agent_name}' },
203
+ { label: 'Ticket Number', value: '{ticket_id}' },
204
+ { label: 'Customer Name', value: '{customer_name}' }
205
+ ];
206
+
207
+ const handleSend = () => {
208
+ // Send message
209
+ setMessage('');
210
+ messageRef.current?.focus();
211
+ };
212
+
213
+ return (
214
+ <div className="chat-composer">
215
+ <VariableField
216
+ ref={messageRef}
217
+ value={message}
218
+ onChange={setMessage}
219
+ options={quickResponses}
220
+ placeholder="Type your message... @ for quick responses"
221
+ inputType="textarea"
222
+ />
223
+ <button onClick={handleSend}>Send</button>
224
+ </div>
225
+ );
226
+ }
227
+ ```
228
+
229
+ ### Custom Variable Categories
230
+ ```jsx
231
+ function CategorizedVariables() {
232
+ const [content, setContent] = useState('');
233
+
234
+ const variables = [
235
+ { label: 'User: Name', value: '{user.name}', category: 'user' },
236
+ { label: 'User: Email', value: '{user.email}', category: 'user' },
237
+ { label: 'Order: ID', value: '{order.id}', category: 'order' },
238
+ { label: 'Order: Total', value: '{order.total}', category: 'order' },
239
+ { label: 'Date: Today', value: '{date.today}', category: 'date' },
240
+ { label: 'Date: Time', value: '{date.time}', category: 'date' }
241
+ ];
242
+
243
+ return (
244
+ <VariableField
245
+ value={content}
246
+ onChange={setContent}
247
+ options={variables}
248
+ label="Content with Variables"
249
+ help="Variables are organized by category for easier selection"
250
+ />
251
+ );
252
+ }
253
+ ```
254
+
255
+ ## Styling
256
+
257
+ The component uses these CSS classes:
258
+
259
+ ```css
260
+ .variable-field-wrapper /* Main wrapper */
261
+ .variable-field-input /* Input element */
262
+ .variable-field-textarea /* Textarea element */
263
+ .variable-field-suggestions /* Suggestions dropdown */
264
+ .variable-field-suggestion /* Individual suggestion */
265
+ .variable-field-suggestion--highlighted /* Highlighted suggestion */
266
+ ```
267
+
268
+ Example custom styling:
269
+ ```css
270
+ .variable-field-suggestions {
271
+ max-height: 200px;
272
+ overflow-y: auto;
273
+ border: 1px solid #ddd;
274
+ border-radius: 4px;
275
+ background: white;
276
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
277
+ }
278
+
279
+ .variable-field-suggestion--highlighted {
280
+ background-color: #f0f0f0;
281
+ }
282
+ ```
283
+
284
+ ## Accessibility
285
+
286
+ - Proper ARIA attributes for autocomplete
287
+ - Keyboard navigation fully supported
288
+ - Screen reader announcements for suggestions
289
+ - Focus management for better UX
290
+ - Descriptive labels and help text support
291
+
292
+ ## Notes
293
+
294
+ - Variables can contain any string format (brackets, braces, etc.)
295
+ - Suggestions appear below the input by default
296
+ - The component handles text selection and cursor position
297
+ - Works with controlled and uncontrolled components
298
+ - Performance optimized with debounced filtering
299
+ - Ref forwarding allows parent components to control focus