@wp-typia/project-tools 0.21.0 → 0.22.1
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/dist/runtime/ai-feature-capability.js +2 -33
- package/dist/runtime/built-in-block-artifact-types.js +11 -0
- package/dist/runtime/built-in-block-code-artifacts.js +5 -1
- package/dist/runtime/built-in-block-code-templates/interactivity.d.ts +4 -3
- package/dist/runtime/built-in-block-code-templates/interactivity.js +259 -100
- package/dist/runtime/built-in-block-code-templates.d.ts +1 -1
- package/dist/runtime/built-in-block-code-templates.js +1 -1
- package/dist/runtime/cli-add-shared.d.ts +4 -3
- package/dist/runtime/cli-add-shared.js +5 -2
- package/dist/runtime/cli-add-workspace-ability.js +3 -4
- package/dist/runtime/cli-add-workspace-admin-view-scaffold.d.ts +9 -0
- package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +257 -0
- package/dist/runtime/cli-add-workspace-admin-view-source.d.ts +5 -0
- package/dist/runtime/cli-add-workspace-admin-view-source.js +86 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates.d.ts +23 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates.js +991 -0
- package/dist/runtime/cli-add-workspace-admin-view-types.d.ts +29 -0
- package/dist/runtime/cli-add-workspace-admin-view-types.js +29 -0
- package/dist/runtime/cli-add-workspace-admin-view.d.ts +1 -14
- package/dist/runtime/cli-add-workspace-admin-view.js +23 -860
- package/dist/runtime/cli-doctor-workspace.js +5 -4
- package/dist/runtime/cli-help.js +5 -2
- package/dist/runtime/external-layer-selection.d.ts +8 -2
- package/dist/runtime/external-layer-selection.js +3 -4
- package/dist/runtime/package-versions.d.ts +28 -0
- package/dist/runtime/package-versions.js +79 -36
- package/dist/runtime/scaffold-compatibility.d.ts +2 -2
- package/dist/runtime/scaffold-compatibility.js +22 -48
- package/dist/runtime/string-case.d.ts +7 -0
- package/dist/runtime/string-case.js +21 -11
- package/dist/runtime/version-floor.d.ts +26 -0
- package/dist/runtime/version-floor.js +56 -0
- package/dist/runtime/workspace-inventory.d.ts +2 -1
- package/package.json +3 -2
|
@@ -4,6 +4,7 @@ import { useBlockProps, InspectorControls, RichText, BlockControls, AlignmentToo
|
|
|
4
4
|
import { PanelBody, RangeControl, Button, Notice } from '@wordpress/components';
|
|
5
5
|
import { useState } from '@wordpress/element';
|
|
6
6
|
import currentManifest from './manifest-document';
|
|
7
|
+
import { {{slugCamelCase}}Store } from './interactivity-store';
|
|
7
8
|
import {
|
|
8
9
|
InspectorFromManifest,
|
|
9
10
|
useEditorFields,
|
|
@@ -84,17 +85,22 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
84
85
|
|
|
85
86
|
const blockProps = useBlockProps({
|
|
86
87
|
className: \`{{cssClassName}} {{cssClassName}}--\${interactiveMode}\`,
|
|
87
|
-
'data-wp-interactive':
|
|
88
|
-
'data-wp-context': JSON.stringify(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
'data-wp-interactive': {{slugCamelCase}}Store.directive.interactive,
|
|
89
|
+
'data-wp-context': JSON.stringify(
|
|
90
|
+
{{slugCamelCase}}Store.createContext({
|
|
91
|
+
clicks: clickCount,
|
|
92
|
+
isAnimating,
|
|
93
|
+
isVisible,
|
|
94
|
+
animation,
|
|
95
|
+
maxClicks,
|
|
96
|
+
})
|
|
97
|
+
)
|
|
95
98
|
});
|
|
96
99
|
const previewContentStyle = { textAlign: alignmentValue };
|
|
97
100
|
const progressBarStyle = { width: \`\${(clickCount / maxClicks) * 100}%\` };
|
|
101
|
+
const clicksDirective = {{slugCamelCase}}Store.directive.state('clicks');
|
|
102
|
+
const isAnimatingDirective = {{slugCamelCase}}Store.directive.state('isAnimating');
|
|
103
|
+
const progressDirective = {{slugCamelCase}}Store.directive.state('progress') + " + '%'";
|
|
98
104
|
|
|
99
105
|
const resetCounter = () => {
|
|
100
106
|
updateField('clickCount', 0);
|
|
@@ -191,9 +197,9 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
191
197
|
<div
|
|
192
198
|
className={\`{{cssClassName}}__content \${isAnimating ? 'is-animating' : ''}\`}
|
|
193
199
|
style={previewContentStyle}
|
|
194
|
-
data-wp-on--click={isPreviewing ? '
|
|
195
|
-
data-wp-on--mouseenter={isPreviewing && interactiveMode === 'hover' ? '
|
|
196
|
-
data-wp-on--mouseleave={isPreviewing && interactiveMode === 'hover' ? '
|
|
200
|
+
data-wp-on--click={isPreviewing ? {{slugCamelCase}}Store.directive.action('handleClick') : undefined}
|
|
201
|
+
data-wp-on--mouseenter={isPreviewing && interactiveMode === 'hover' ? {{slugCamelCase}}Store.directive.action('handleMouseEnter') : undefined}
|
|
202
|
+
data-wp-on--mouseleave={isPreviewing && interactiveMode === 'hover' ? {{slugCamelCase}}Store.directive.action('handleMouseLeave') : undefined}
|
|
197
203
|
>
|
|
198
204
|
<RichText
|
|
199
205
|
tagName="p"
|
|
@@ -222,7 +228,7 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
222
228
|
</span>
|
|
223
229
|
<span
|
|
224
230
|
className="{{cssClassName}}__counter-value"
|
|
225
|
-
data-wp-text=
|
|
231
|
+
data-wp-text={clicksDirective}
|
|
226
232
|
>
|
|
227
233
|
{clickCount}
|
|
228
234
|
</span>
|
|
@@ -234,7 +240,7 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
234
240
|
<div
|
|
235
241
|
className="{{cssClassName}}__progress-bar"
|
|
236
242
|
style={progressBarStyle}
|
|
237
|
-
data-wp-style--width=
|
|
243
|
+
data-wp-style--width={progressDirective}
|
|
238
244
|
/>
|
|
239
245
|
</div>
|
|
240
246
|
)}
|
|
@@ -242,7 +248,7 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
242
248
|
{animation !== 'none' && (
|
|
243
249
|
<div
|
|
244
250
|
className={\`{{cssClassName}}__animation \${isAnimating ? 'is-active' : ''}\`}
|
|
245
|
-
data-wp-class--is-active=
|
|
251
|
+
data-wp-class--is-active={isAnimatingDirective}
|
|
246
252
|
>
|
|
247
253
|
{animation}
|
|
248
254
|
</div>
|
|
@@ -255,6 +261,7 @@ export default function Edit({ attributes, setAttributes, isSelected }: EditProp
|
|
|
255
261
|
`;
|
|
256
262
|
export const INTERACTIVITY_SAVE_TEMPLATE = `import { useBlockProps, RichText } from '@wordpress/block-editor';
|
|
257
263
|
import { __ } from '@wordpress/i18n';
|
|
264
|
+
import { {{slugCamelCase}}Store } from './interactivity-store';
|
|
258
265
|
import type { {{pascalCase}}Attributes } from './types';
|
|
259
266
|
|
|
260
267
|
export default function Save({ attributes }: { attributes: {{pascalCase}}Attributes }) {
|
|
@@ -266,27 +273,41 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
266
273
|
const maxClicks = attributes.maxClicks ?? 0;
|
|
267
274
|
const showCounter = attributes.showCounter ?? true;
|
|
268
275
|
const contentStyle = { textAlign: attributes.alignment };
|
|
276
|
+
const clickActionDirective = {{slugCamelCase}}Store.directive.action('handleClick');
|
|
277
|
+
const visibilityHiddenDirective = {{slugCamelCase}}Store.directive.negate(
|
|
278
|
+
{{slugCamelCase}}Store.directive.state('isVisible')
|
|
279
|
+
);
|
|
280
|
+
const clicksDirective = {{slugCamelCase}}Store.directive.state('clicks');
|
|
281
|
+
const clampedClicksDirective = {{slugCamelCase}}Store.directive.state('clampedClicks');
|
|
282
|
+
const isAnimatingDirective = {{slugCamelCase}}Store.directive.state('isAnimating');
|
|
283
|
+
const completionHiddenDirective = {{slugCamelCase}}Store.directive.negate(
|
|
284
|
+
{{slugCamelCase}}Store.directive.state('isComplete')
|
|
285
|
+
);
|
|
286
|
+
const resetActionDirective = {{slugCamelCase}}Store.directive.action('reset');
|
|
269
287
|
const blockProps = useBlockProps.save({
|
|
270
288
|
className: \`{{cssClassName}} {{cssClassName}}--\${interactiveMode}\`,
|
|
271
|
-
'data-wp-interactive':
|
|
272
|
-
'data-wp-context': JSON.stringify(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
289
|
+
'data-wp-interactive': {{slugCamelCase}}Store.directive.interactive,
|
|
290
|
+
'data-wp-context': JSON.stringify(
|
|
291
|
+
{{slugCamelCase}}Store.createContext({
|
|
292
|
+
clicks: clickCount,
|
|
293
|
+
isAnimating,
|
|
294
|
+
isVisible,
|
|
295
|
+
animation,
|
|
296
|
+
maxClicks,
|
|
297
|
+
})
|
|
298
|
+
)
|
|
279
299
|
});
|
|
300
|
+
const progressDirective = {{slugCamelCase}}Store.directive.state('progress') + " + '%'";
|
|
280
301
|
|
|
281
302
|
return (
|
|
282
303
|
<div {...blockProps}>
|
|
283
304
|
<div
|
|
284
305
|
className={\`{{cssClassName}}__content \${isAnimating ? 'is-animating' : ''}\`}
|
|
285
306
|
style={contentStyle}
|
|
286
|
-
data-wp-on--click=
|
|
287
|
-
data-wp-on--mouseenter={interactiveMode === 'hover' ? '
|
|
288
|
-
data-wp-on--mouseleave={interactiveMode === 'hover' ? '
|
|
289
|
-
data-wp-bind--hidden=
|
|
307
|
+
data-wp-on--click={clickActionDirective}
|
|
308
|
+
data-wp-on--mouseenter={interactiveMode === 'hover' ? {{slugCamelCase}}Store.directive.action('handleMouseEnter') : undefined}
|
|
309
|
+
data-wp-on--mouseleave={interactiveMode === 'hover' ? {{slugCamelCase}}Store.directive.action('handleMouseLeave') : undefined}
|
|
310
|
+
data-wp-bind--hidden={visibilityHiddenDirective}
|
|
290
311
|
>
|
|
291
312
|
<RichText.Content
|
|
292
313
|
tagName="p"
|
|
@@ -306,7 +327,7 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
306
327
|
</span>
|
|
307
328
|
<span
|
|
308
329
|
className="{{cssClassName}}__counter-value"
|
|
309
|
-
data-wp-text=
|
|
330
|
+
data-wp-text={clicksDirective}
|
|
310
331
|
>
|
|
311
332
|
{clickCount}
|
|
312
333
|
</span>
|
|
@@ -322,8 +343,8 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
322
343
|
aria-valuemin={0}
|
|
323
344
|
aria-valuemax={maxClicks}
|
|
324
345
|
aria-valuenow={Math.min(clickCount, maxClicks)}
|
|
325
|
-
data-wp-bind--aria-valuenow=
|
|
326
|
-
data-wp-style--width=
|
|
346
|
+
data-wp-bind--aria-valuenow={clampedClicksDirective}
|
|
347
|
+
data-wp-style--width={progressDirective}
|
|
327
348
|
/>
|
|
328
349
|
</div>
|
|
329
350
|
)}
|
|
@@ -331,7 +352,7 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
331
352
|
<div
|
|
332
353
|
className={\`{{cssClassName}}__animation \${animation}\`}
|
|
333
354
|
aria-hidden="true"
|
|
334
|
-
data-wp-class--is-active=
|
|
355
|
+
data-wp-class--is-active={isAnimatingDirective}
|
|
335
356
|
/>
|
|
336
357
|
|
|
337
358
|
{maxClicks > 0 && (
|
|
@@ -340,7 +361,7 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
340
361
|
role="status"
|
|
341
362
|
aria-live="polite"
|
|
342
363
|
aria-atomic="true"
|
|
343
|
-
data-wp-bind--hidden=
|
|
364
|
+
data-wp-bind--hidden={completionHiddenDirective}
|
|
344
365
|
>
|
|
345
366
|
{ __( '🎉 Complete!', '{{textDomain}}' ) }
|
|
346
367
|
</div>
|
|
@@ -348,7 +369,7 @@ export default function Save({ attributes }: { attributes: {{pascalCase}}Attribu
|
|
|
348
369
|
|
|
349
370
|
<button
|
|
350
371
|
className="{{cssClassName}}__reset"
|
|
351
|
-
data-wp-on--click=
|
|
372
|
+
data-wp-on--click={resetActionDirective}
|
|
352
373
|
aria-label={ __( 'Reset counter', '{{textDomain}}' ) }
|
|
353
374
|
>
|
|
354
375
|
<span aria-hidden="true">↻</span>
|
|
@@ -398,20 +419,214 @@ const registration = buildScaffoldBlockRegistration(
|
|
|
398
419
|
|
|
399
420
|
registerScaffoldBlockType(registration.name, registration.settings);
|
|
400
421
|
`;
|
|
422
|
+
export const INTERACTIVITY_STORE_TEMPLATE = `import type {
|
|
423
|
+
{{pascalCase}}Context,
|
|
424
|
+
{{pascalCase}}State,
|
|
425
|
+
} from './types';
|
|
426
|
+
|
|
427
|
+
type InteractivityActionShape = object;
|
|
428
|
+
type InteractivityCallbackShape = object;
|
|
429
|
+
type InteractivityContextShape = object;
|
|
430
|
+
type InteractivityStateShape = object;
|
|
431
|
+
type InteractivityCallable = CallableFunction;
|
|
432
|
+
type InteractivityKey<T extends object> = Extract<keyof T, string>;
|
|
433
|
+
type InteractivityMethodKey<T extends object> = {
|
|
434
|
+
[Key in InteractivityKey<T>]: T[Key] extends InteractivityCallable ? Key : never;
|
|
435
|
+
}[InteractivityKey<T>];
|
|
436
|
+
|
|
437
|
+
type InteractivityDirectivePath<
|
|
438
|
+
Root extends string,
|
|
439
|
+
Key extends string,
|
|
440
|
+
> = \`\${Root}.\${Key}\`;
|
|
441
|
+
|
|
442
|
+
type NegatedInteractivityDirectivePath<Path extends string> = \`!\${Path}\`;
|
|
443
|
+
|
|
444
|
+
export interface TypedInteractivityDirectiveHelpers<
|
|
445
|
+
State extends InteractivityStateShape,
|
|
446
|
+
Context extends InteractivityContextShape,
|
|
447
|
+
Actions extends InteractivityActionShape,
|
|
448
|
+
Callbacks extends InteractivityCallbackShape,
|
|
449
|
+
Namespace extends string,
|
|
450
|
+
> {
|
|
451
|
+
readonly interactive: Namespace;
|
|
452
|
+
action<Key extends InteractivityMethodKey<Actions>>(
|
|
453
|
+
key: Key,
|
|
454
|
+
): InteractivityDirectivePath<'actions', Key>;
|
|
455
|
+
callback<Key extends InteractivityMethodKey<Callbacks>>(
|
|
456
|
+
key: Key,
|
|
457
|
+
): InteractivityDirectivePath<'callbacks', Key>;
|
|
458
|
+
state<Key extends InteractivityKey<State>>(
|
|
459
|
+
key: Key,
|
|
460
|
+
): InteractivityDirectivePath<'state', Key>;
|
|
461
|
+
context<Key extends InteractivityKey<Context>>(
|
|
462
|
+
key: Key,
|
|
463
|
+
): InteractivityDirectivePath<'context', Key>;
|
|
464
|
+
negate<Path extends string>(
|
|
465
|
+
path: Path,
|
|
466
|
+
): NegatedInteractivityDirectivePath<Path>;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export interface TypedInteractivityStore<
|
|
470
|
+
Namespace extends string,
|
|
471
|
+
State extends InteractivityStateShape,
|
|
472
|
+
Context extends InteractivityContextShape,
|
|
473
|
+
Actions extends InteractivityActionShape,
|
|
474
|
+
Callbacks extends InteractivityCallbackShape,
|
|
475
|
+
> {
|
|
476
|
+
readonly namespace: Namespace;
|
|
477
|
+
readonly state: State;
|
|
478
|
+
readonly context: Context;
|
|
479
|
+
readonly actions: Actions;
|
|
480
|
+
readonly callbacks: Callbacks;
|
|
481
|
+
readonly directive: TypedInteractivityDirectiveHelpers<
|
|
482
|
+
State,
|
|
483
|
+
Context,
|
|
484
|
+
Actions,
|
|
485
|
+
Callbacks,
|
|
486
|
+
Namespace
|
|
487
|
+
>;
|
|
488
|
+
createContext(value: Context): Context;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export function defineInteractivityStore<
|
|
492
|
+
Namespace extends string,
|
|
493
|
+
State extends InteractivityStateShape,
|
|
494
|
+
Context extends InteractivityContextShape,
|
|
495
|
+
Actions extends InteractivityActionShape,
|
|
496
|
+
Callbacks extends InteractivityCallbackShape,
|
|
497
|
+
>(config: {
|
|
498
|
+
readonly namespace: Namespace;
|
|
499
|
+
readonly state: State;
|
|
500
|
+
readonly context: Context;
|
|
501
|
+
readonly actions: Actions;
|
|
502
|
+
readonly callbacks: Callbacks;
|
|
503
|
+
}): TypedInteractivityStore<Namespace, State, Context, Actions, Callbacks> {
|
|
504
|
+
return {
|
|
505
|
+
namespace: config.namespace,
|
|
506
|
+
state: config.state,
|
|
507
|
+
context: config.context,
|
|
508
|
+
actions: config.actions,
|
|
509
|
+
callbacks: config.callbacks,
|
|
510
|
+
directive: {
|
|
511
|
+
interactive: config.namespace,
|
|
512
|
+
action<Key extends InteractivityMethodKey<Actions>>(key: Key) {
|
|
513
|
+
return \`actions.\${key}\` as InteractivityDirectivePath<'actions', Key>;
|
|
514
|
+
},
|
|
515
|
+
callback<Key extends InteractivityMethodKey<Callbacks>>(key: Key) {
|
|
516
|
+
return \`callbacks.\${key}\` as InteractivityDirectivePath<'callbacks', Key>;
|
|
517
|
+
},
|
|
518
|
+
state<Key extends InteractivityKey<State>>(key: Key) {
|
|
519
|
+
return \`state.\${key}\` as InteractivityDirectivePath<'state', Key>;
|
|
520
|
+
},
|
|
521
|
+
context<Key extends InteractivityKey<Context>>(key: Key) {
|
|
522
|
+
return \`context.\${key}\` as InteractivityDirectivePath<'context', Key>;
|
|
523
|
+
},
|
|
524
|
+
negate<Path extends string>(path: Path) {
|
|
525
|
+
return \`!\${path}\` as NegatedInteractivityDirectivePath<Path>;
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
createContext(value) {
|
|
529
|
+
return value;
|
|
530
|
+
},
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
type InteractivityActionHandler = CallableFunction;
|
|
535
|
+
|
|
536
|
+
export interface {{pascalCase}}StoreActions {
|
|
537
|
+
handleClick: InteractivityActionHandler;
|
|
538
|
+
handleMouseEnter: InteractivityActionHandler;
|
|
539
|
+
handleMouseLeave: InteractivityActionHandler;
|
|
540
|
+
reset: InteractivityActionHandler;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
export interface {{pascalCase}}StoreCallbacks {}
|
|
544
|
+
|
|
545
|
+
export const {{slugCamelCase}}Store = defineInteractivityStore({
|
|
546
|
+
namespace: '{{slugKebabCase}}',
|
|
547
|
+
state: {} as {{pascalCase}}State,
|
|
548
|
+
context: {} as {{pascalCase}}Context,
|
|
549
|
+
actions: {} as {{pascalCase}}StoreActions,
|
|
550
|
+
callbacks: {} as {{pascalCase}}StoreCallbacks,
|
|
551
|
+
});
|
|
552
|
+
`;
|
|
401
553
|
export const INTERACTIVITY_SCRIPT_TEMPLATE = `/**
|
|
402
554
|
* WordPress Interactivity API implementation for {{title}} block
|
|
403
555
|
*/
|
|
404
556
|
import { store, getContext, getElement, withSyncEvent } from '@wordpress/interactivity';
|
|
405
|
-
import
|
|
557
|
+
import {
|
|
558
|
+
{{slugCamelCase}}Store,
|
|
559
|
+
type {{pascalCase}}StoreActions,
|
|
560
|
+
} from './interactivity-store';
|
|
561
|
+
import type { {{pascalCase}}Context, {{pascalCase}}State } from './types';
|
|
406
562
|
|
|
407
563
|
function getBlockContext() {
|
|
408
564
|
return getContext<{{pascalCase}}Context>();
|
|
409
565
|
}
|
|
410
566
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
567
|
+
const actions: {{pascalCase}}StoreActions = {
|
|
568
|
+
// Handle block click
|
|
569
|
+
handleClick: () => {
|
|
570
|
+
const context = getBlockContext();
|
|
571
|
+
const { ref } = getElement();
|
|
572
|
+
|
|
573
|
+
if (!ref) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
if (context.maxClicks > 0 && context.clicks >= context.maxClicks) {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const previousClicks = context.clicks;
|
|
582
|
+
|
|
583
|
+
// Increment click counter
|
|
584
|
+
context.clicks += 1;
|
|
585
|
+
|
|
586
|
+
// Trigger animation
|
|
587
|
+
if (context.animation !== 'none') {
|
|
588
|
+
context.isAnimating = true;
|
|
589
|
+
setTimeout(() => {
|
|
590
|
+
context.isAnimating = false;
|
|
591
|
+
}, 1000);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Emit custom event
|
|
595
|
+
ref.dispatchEvent(new CustomEvent('{{slugKebabCase}}:click', {
|
|
596
|
+
detail: { clicks: context.clicks }
|
|
597
|
+
}));
|
|
598
|
+
|
|
599
|
+
// Check if max clicks reached
|
|
600
|
+
if (context.maxClicks > 0 && previousClicks < context.maxClicks && context.clicks === context.maxClicks) {
|
|
601
|
+
ref.dispatchEvent(new CustomEvent('{{slugKebabCase}}:complete', {
|
|
602
|
+
detail: { totalClicks: context.clicks }
|
|
603
|
+
}));
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
|
|
607
|
+
// Handle hover events
|
|
608
|
+
handleMouseEnter: () => {
|
|
609
|
+
const context = getBlockContext();
|
|
610
|
+
if (context.animation === 'none') return;
|
|
611
|
+
context.isAnimating = true;
|
|
612
|
+
},
|
|
613
|
+
|
|
614
|
+
handleMouseLeave: () => {
|
|
615
|
+
const context = getBlockContext();
|
|
616
|
+
if (context.animation === 'none') return;
|
|
617
|
+
context.isAnimating = false;
|
|
618
|
+
},
|
|
619
|
+
|
|
620
|
+
// Reset counter
|
|
621
|
+
reset: withSyncEvent((event: Event) => {
|
|
622
|
+
event.stopPropagation();
|
|
623
|
+
const context = getBlockContext();
|
|
624
|
+
context.clicks = 0;
|
|
625
|
+
context.isAnimating = false;
|
|
626
|
+
})
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
const state = {
|
|
415
630
|
get clicks() {
|
|
416
631
|
return getBlockContext().clicks;
|
|
417
632
|
},
|
|
@@ -439,70 +654,14 @@ store('{{slugKebabCase}}', {
|
|
|
439
654
|
const context = getBlockContext();
|
|
440
655
|
return context.clicks >= context.maxClicks && context.maxClicks > 0;
|
|
441
656
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
// Actions - user interactions
|
|
445
|
-
actions: {
|
|
446
|
-
// Handle block click
|
|
447
|
-
handleClick: () => {
|
|
448
|
-
const context = getBlockContext();
|
|
449
|
-
const { ref } = getElement();
|
|
450
|
-
|
|
451
|
-
if (!ref) {
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
if (context.maxClicks > 0 && context.clicks >= context.maxClicks) {
|
|
456
|
-
return;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
const previousClicks = context.clicks;
|
|
460
|
-
|
|
461
|
-
// Increment click counter
|
|
462
|
-
context.clicks += 1;
|
|
657
|
+
} satisfies {{pascalCase}}State;
|
|
463
658
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
// Emit custom event
|
|
473
|
-
ref.dispatchEvent(new CustomEvent('{{slugKebabCase}}:click', {
|
|
474
|
-
detail: { clicks: context.clicks }
|
|
475
|
-
}));
|
|
476
|
-
|
|
477
|
-
// Check if max clicks reached
|
|
478
|
-
if (context.maxClicks > 0 && previousClicks < context.maxClicks && context.clicks === context.maxClicks) {
|
|
479
|
-
ref.dispatchEvent(new CustomEvent('{{slugKebabCase}}:complete', {
|
|
480
|
-
detail: { totalClicks: context.clicks }
|
|
481
|
-
}));
|
|
482
|
-
}
|
|
483
|
-
},
|
|
484
|
-
|
|
485
|
-
// Handle hover events
|
|
486
|
-
handleMouseEnter: () => {
|
|
487
|
-
const context = getBlockContext();
|
|
488
|
-
if (context.animation === 'none') return;
|
|
489
|
-
context.isAnimating = true;
|
|
490
|
-
},
|
|
491
|
-
|
|
492
|
-
handleMouseLeave: () => {
|
|
493
|
-
const context = getBlockContext();
|
|
494
|
-
if (context.animation === 'none') return;
|
|
495
|
-
context.isAnimating = false;
|
|
496
|
-
},
|
|
497
|
-
|
|
498
|
-
// Reset counter
|
|
499
|
-
reset: withSyncEvent((event: Event) => {
|
|
500
|
-
event.stopPropagation();
|
|
501
|
-
const context = getBlockContext();
|
|
502
|
-
context.clicks = 0;
|
|
503
|
-
context.isAnimating = false;
|
|
504
|
-
})
|
|
505
|
-
}
|
|
659
|
+
// Store configuration
|
|
660
|
+
store({{slugCamelCase}}Store.namespace, {
|
|
661
|
+
// State - reactive data that updates the UI
|
|
662
|
+
state,
|
|
663
|
+
actions,
|
|
664
|
+
callbacks: {{slugCamelCase}}Store.callbacks,
|
|
506
665
|
});
|
|
507
666
|
`;
|
|
508
667
|
export const INTERACTIVITY_VALIDATORS_TEMPLATE = `import typia from 'typia';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { BLOCK_METADATA_WRAPPER_TEMPLATE, MANIFEST_DEFAULTS_DOCUMENT_WRAPPER_TEMPLATE, MANIFEST_DOCUMENT_WRAPPER_TEMPLATE, SHARED_HOOKS_TEMPLATE, } from "./built-in-block-code-templates/shared.js";
|
|
6
6
|
export { BASIC_EDIT_TEMPLATE, BASIC_INDEX_TEMPLATE, BASIC_SAVE_TEMPLATE, BASIC_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/basic.js";
|
|
7
|
-
export { INTERACTIVITY_EDIT_TEMPLATE, INTERACTIVITY_INDEX_TEMPLATE, INTERACTIVITY_SAVE_TEMPLATE, INTERACTIVITY_SCRIPT_TEMPLATE, INTERACTIVITY_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/interactivity.js";
|
|
7
|
+
export { INTERACTIVITY_EDIT_TEMPLATE, INTERACTIVITY_INDEX_TEMPLATE, INTERACTIVITY_SAVE_TEMPLATE, INTERACTIVITY_SCRIPT_TEMPLATE, INTERACTIVITY_STORE_TEMPLATE, INTERACTIVITY_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/interactivity.js";
|
|
8
8
|
export { PERSISTENCE_EDIT_TEMPLATE, PERSISTENCE_INDEX_TEMPLATE, PERSISTENCE_INTERACTIVITY_TEMPLATE, PERSISTENCE_SAVE_TEMPLATE, PERSISTENCE_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/persistence.js";
|
|
9
9
|
export { QUERY_LOOP_INDEX_TEMPLATE, } from "./built-in-block-code-templates/query-loop.js";
|
|
10
10
|
export { COMPOUND_CHILD_EDIT_TEMPLATE, COMPOUND_CHILD_INDEX_TEMPLATE, COMPOUND_CHILDREN_TEMPLATE, COMPOUND_CHILD_SAVE_TEMPLATE, COMPOUND_CHILD_VALIDATORS_TEMPLATE, COMPOUND_LOCAL_HOOKS_TEMPLATE, COMPOUND_PARENT_EDIT_TEMPLATE, COMPOUND_PARENT_INDEX_TEMPLATE, COMPOUND_PARENT_SAVE_TEMPLATE, COMPOUND_PARENT_VALIDATORS_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_EDIT_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_INTERACTIVITY_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_SAVE_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/compound.js";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { BLOCK_METADATA_WRAPPER_TEMPLATE, MANIFEST_DEFAULTS_DOCUMENT_WRAPPER_TEMPLATE, MANIFEST_DOCUMENT_WRAPPER_TEMPLATE, SHARED_HOOKS_TEMPLATE, } from "./built-in-block-code-templates/shared.js";
|
|
6
6
|
export { BASIC_EDIT_TEMPLATE, BASIC_INDEX_TEMPLATE, BASIC_SAVE_TEMPLATE, BASIC_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/basic.js";
|
|
7
|
-
export { INTERACTIVITY_EDIT_TEMPLATE, INTERACTIVITY_INDEX_TEMPLATE, INTERACTIVITY_SAVE_TEMPLATE, INTERACTIVITY_SCRIPT_TEMPLATE, INTERACTIVITY_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/interactivity.js";
|
|
7
|
+
export { INTERACTIVITY_EDIT_TEMPLATE, INTERACTIVITY_INDEX_TEMPLATE, INTERACTIVITY_SAVE_TEMPLATE, INTERACTIVITY_SCRIPT_TEMPLATE, INTERACTIVITY_STORE_TEMPLATE, INTERACTIVITY_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/interactivity.js";
|
|
8
8
|
export { PERSISTENCE_EDIT_TEMPLATE, PERSISTENCE_INDEX_TEMPLATE, PERSISTENCE_INTERACTIVITY_TEMPLATE, PERSISTENCE_SAVE_TEMPLATE, PERSISTENCE_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/persistence.js";
|
|
9
9
|
export { QUERY_LOOP_INDEX_TEMPLATE, } from "./built-in-block-code-templates/query-loop.js";
|
|
10
10
|
export { COMPOUND_CHILD_EDIT_TEMPLATE, COMPOUND_CHILD_INDEX_TEMPLATE, COMPOUND_CHILDREN_TEMPLATE, COMPOUND_CHILD_SAVE_TEMPLATE, COMPOUND_CHILD_VALIDATORS_TEMPLATE, COMPOUND_LOCAL_HOOKS_TEMPLATE, COMPOUND_PARENT_EDIT_TEMPLATE, COMPOUND_PARENT_INDEX_TEMPLATE, COMPOUND_PARENT_SAVE_TEMPLATE, COMPOUND_PARENT_VALIDATORS_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_EDIT_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_INTERACTIVITY_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_SAVE_TEMPLATE, COMPOUND_PERSISTENCE_PARENT_VALIDATORS_TEMPLATE, } from "./built-in-block-code-templates/compound.js";
|
|
@@ -92,9 +92,10 @@ export interface RunAddRestResourceCommandOptions {
|
|
|
92
92
|
* normalized into the generated slug.
|
|
93
93
|
* @property cwd Working directory used to resolve the nearest official workspace.
|
|
94
94
|
* Defaults to `process.cwd()`.
|
|
95
|
-
* @property source Optional data source locator.
|
|
96
|
-
*
|
|
97
|
-
*
|
|
95
|
+
* @property source Optional data source locator. `rest-resource:<slug>` wires
|
|
96
|
+
* the generated screen to an existing list-capable REST resource.
|
|
97
|
+
* `core-data:<kind>/<name>` binds the screen to a supported WordPress-owned
|
|
98
|
+
* entity collection such as `core-data:postType/post`.
|
|
98
99
|
*/
|
|
99
100
|
export interface RunAddAdminViewCommandOptions {
|
|
100
101
|
adminViewName: string;
|
|
@@ -357,7 +357,7 @@ export function assertEditorPluginDoesNotExist(projectDir, editorPluginSlug, inv
|
|
|
357
357
|
*/
|
|
358
358
|
export function formatAddHelpText() {
|
|
359
359
|
return `Usage:
|
|
360
|
-
wp-typia add admin-view <name> [--source <rest-resource:slug>] [--dry-run]
|
|
360
|
+
wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>] [--dry-run]
|
|
361
361
|
wp-typia add block <name> [--template <${ADD_BLOCK_TEMPLATE_IDS.join("|")}>] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--inner-blocks-preset <freeform|ordered|horizontal|locked-structure>] [--alternate-render-targets <email,mjml,plain-text>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--dry-run]
|
|
362
362
|
wp-typia add variation <name> --block <block-slug> [--dry-run]
|
|
363
363
|
wp-typia add style <name> --block <block-slug> [--dry-run]
|
|
@@ -374,7 +374,10 @@ Notes:
|
|
|
374
374
|
\`wp-typia add\` runs only inside official ${WORKSPACE_TEMPLATE_PACKAGE} workspaces scaffolded via \`wp-typia create <project-dir> --template workspace\`.
|
|
375
375
|
Pass \`--dry-run\` to preview the workspace files that would change without writing them.
|
|
376
376
|
Interactive add flows let you choose a template when \`--template\` is omitted; non-interactive runs default to \`basic\`.
|
|
377
|
-
\`add admin-view\` scaffolds an opt-in DataViews-powered WordPress admin screen under \`src/admin-views
|
|
377
|
+
\`add admin-view\` scaffolds an opt-in DataViews-powered WordPress admin screen under \`src/admin-views/\`.
|
|
378
|
+
Pass \`--source rest-resource:<slug>\` to reuse a list-capable REST resource.
|
|
379
|
+
Pass \`--source core-data:postType/post\` or \`--source core-data:taxonomy/category\` to bind a WordPress-owned entity collection.
|
|
380
|
+
Public installs currently gate this workflow until \`@wp-typia/dataviews\` is published to npm.
|
|
378
381
|
\`query-loop\` is a create-time scaffold family. Use \`wp-typia create <project-dir> --template query-loop\` instead of \`wp-typia add block\`.
|
|
379
382
|
\`add variation\` targets an existing block slug from \`scripts/block-config.ts\`.
|
|
380
383
|
\`add style\` registers a Block Styles option for an existing generated block.
|
|
@@ -9,13 +9,12 @@ import { toPascalCase, toTitleCase } from "./string-case.js";
|
|
|
9
9
|
import { escapeRegex, findPhpFunctionRange, hasPhpFunctionDefinition, quotePhpString, replacePhpFunctionDefinition, } from "./php-utils.js";
|
|
10
10
|
import { assertAbilityDoesNotExist, assertValidGeneratedSlug, getWorkspaceBootstrapPath, normalizeBlockSlug, patchFile, quoteTsString, rollbackWorkspaceMutation, snapshotWorkspaceFiles, } from "./cli-add-shared.js";
|
|
11
11
|
import { REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY, renderScaffoldCompatibilityConfig, resolveScaffoldCompatibilityPolicy, updatePluginHeaderCompatibility, } from "./scaffold-compatibility.js";
|
|
12
|
+
import { DEFAULT_WORDPRESS_ABILITIES_VERSION, DEFAULT_WORDPRESS_CORE_ABILITIES_VERSION, } from "./package-versions.js";
|
|
12
13
|
const ABILITY_SERVER_GLOB = "/inc/abilities/*.php";
|
|
13
14
|
const ABILITY_EDITOR_SCRIPT = "build/abilities/index.js";
|
|
14
15
|
const ABILITY_EDITOR_ASSET = "build/abilities/index.asset.php";
|
|
15
16
|
const ABILITY_REGISTRY_END_MARKER = "// wp-typia add ability entries end";
|
|
16
17
|
const ABILITY_REGISTRY_START_MARKER = "// wp-typia add ability entries start";
|
|
17
|
-
const WP_ABILITIES_PACKAGE_VERSION = "^0.10.0";
|
|
18
|
-
const WP_CORE_ABILITIES_PACKAGE_VERSION = "^0.9.0";
|
|
19
18
|
const WP_ABILITIES_SCRIPT_MODULE_ID = "@wordpress/abilities";
|
|
20
19
|
const WP_CORE_ABILITIES_SCRIPT_MODULE_ID = "@wordpress/core-abilities";
|
|
21
20
|
function resolveManagedDependencyVersion(existingVersion, requiredVersion) {
|
|
@@ -654,8 +653,8 @@ async function ensureAbilityPackageScripts(workspace) {
|
|
|
654
653
|
};
|
|
655
654
|
const nextDependencies = {
|
|
656
655
|
...(packageJson.dependencies ?? {}),
|
|
657
|
-
[WP_ABILITIES_SCRIPT_MODULE_ID]: resolveManagedDependencyVersion(packageJson.dependencies?.[WP_ABILITIES_SCRIPT_MODULE_ID],
|
|
658
|
-
[WP_CORE_ABILITIES_SCRIPT_MODULE_ID]: resolveManagedDependencyVersion(packageJson.dependencies?.[WP_CORE_ABILITIES_SCRIPT_MODULE_ID],
|
|
656
|
+
[WP_ABILITIES_SCRIPT_MODULE_ID]: resolveManagedDependencyVersion(packageJson.dependencies?.[WP_ABILITIES_SCRIPT_MODULE_ID], DEFAULT_WORDPRESS_ABILITIES_VERSION),
|
|
657
|
+
[WP_CORE_ABILITIES_SCRIPT_MODULE_ID]: resolveManagedDependencyVersion(packageJson.dependencies?.[WP_CORE_ABILITIES_SCRIPT_MODULE_ID], DEFAULT_WORDPRESS_CORE_ABILITIES_VERSION),
|
|
659
658
|
};
|
|
660
659
|
if (JSON.stringify(nextScripts) === JSON.stringify(packageJson.scripts ?? {}) &&
|
|
661
660
|
JSON.stringify(nextDependencies) === JSON.stringify(packageJson.dependencies ?? {})) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { WorkspaceProject } from './workspace-project.js';
|
|
2
|
+
import { type AdminViewCoreDataSource, type AdminViewRestResource, type AdminViewSource } from './cli-add-workspace-admin-view-types.js';
|
|
3
|
+
export declare function scaffoldAdminViewWorkspace(options: {
|
|
4
|
+
adminViewSlug: string;
|
|
5
|
+
coreDataSource?: AdminViewCoreDataSource;
|
|
6
|
+
parsedSource?: AdminViewSource;
|
|
7
|
+
restResource?: AdminViewRestResource;
|
|
8
|
+
workspace: WorkspaceProject;
|
|
9
|
+
}): Promise<void>;
|