@wordpress/fields 0.2.0 → 0.3.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.
Files changed (113) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +12 -0
  3. package/build/actions/delete-post.js +4 -4
  4. package/build/actions/delete-post.js.map +1 -1
  5. package/build/actions/duplicate-post.js +2 -2
  6. package/build/actions/duplicate-post.js.map +1 -1
  7. package/build/actions/view-post-revisions.js +1 -1
  8. package/build/actions/view-post-revisions.js.map +1 -1
  9. package/build/fields/featured-image/featured-image-edit.js +113 -0
  10. package/build/fields/featured-image/featured-image-edit.js.map +1 -0
  11. package/build/fields/featured-image/featured-image-view.js +41 -0
  12. package/build/fields/featured-image/featured-image-view.js.map +1 -0
  13. package/build/fields/featured-image/index.js +30 -0
  14. package/build/fields/featured-image/index.js.map +1 -0
  15. package/build/fields/index.js +21 -0
  16. package/build/fields/index.js.map +1 -1
  17. package/build/fields/parent/index.js +34 -0
  18. package/build/fields/parent/index.js.map +1 -0
  19. package/build/fields/parent/parent-edit.js +243 -0
  20. package/build/fields/parent/parent-edit.js.map +1 -0
  21. package/build/fields/parent/parent-view.js +39 -0
  22. package/build/fields/parent/parent-view.js.map +1 -0
  23. package/build/fields/parent/utils.js +20 -0
  24. package/build/fields/parent/utils.js.map +1 -0
  25. package/build/fields/slug/index.js +30 -0
  26. package/build/fields/slug/index.js.map +1 -0
  27. package/build/fields/slug/slug-edit.js +132 -0
  28. package/build/fields/slug/slug-edit.js.map +1 -0
  29. package/build/fields/slug/slug-view.js +30 -0
  30. package/build/fields/slug/slug-view.js.map +1 -0
  31. package/build/mutation/index.js +2 -2
  32. package/build/mutation/index.js.map +1 -1
  33. package/build/types.js.map +1 -1
  34. package/build-module/actions/delete-post.js +5 -5
  35. package/build-module/actions/delete-post.js.map +1 -1
  36. package/build-module/actions/duplicate-post.js +2 -2
  37. package/build-module/actions/duplicate-post.js.map +1 -1
  38. package/build-module/actions/view-post-revisions.js +1 -1
  39. package/build-module/actions/view-post-revisions.js.map +1 -1
  40. package/build-module/fields/featured-image/featured-image-edit.js +105 -0
  41. package/build-module/fields/featured-image/featured-image-edit.js.map +1 -0
  42. package/build-module/fields/featured-image/featured-image-view.js +33 -0
  43. package/build-module/fields/featured-image/featured-image-view.js.map +1 -0
  44. package/build-module/fields/featured-image/index.js +24 -0
  45. package/build-module/fields/featured-image/index.js.map +1 -0
  46. package/build-module/fields/index.js +3 -0
  47. package/build-module/fields/index.js.map +1 -1
  48. package/build-module/fields/parent/index.js +28 -0
  49. package/build-module/fields/parent/index.js.map +1 -0
  50. package/build-module/fields/parent/parent-edit.js +230 -0
  51. package/build-module/fields/parent/parent-edit.js.map +1 -0
  52. package/build-module/fields/parent/parent-view.js +32 -0
  53. package/build-module/fields/parent/parent-view.js.map +1 -0
  54. package/build-module/fields/parent/utils.js +14 -0
  55. package/build-module/fields/parent/utils.js.map +1 -0
  56. package/build-module/fields/slug/index.js +23 -0
  57. package/build-module/fields/slug/index.js.map +1 -0
  58. package/build-module/fields/slug/slug-edit.js +125 -0
  59. package/build-module/fields/slug/slug-edit.js.map +1 -0
  60. package/build-module/fields/slug/slug-view.js +24 -0
  61. package/build-module/fields/slug/slug-view.js.map +1 -0
  62. package/build-module/mutation/index.js +2 -2
  63. package/build-module/mutation/index.js.map +1 -1
  64. package/build-module/types.js.map +1 -1
  65. package/build-style/styles-rtl.css +134 -0
  66. package/build-style/styles.css +134 -0
  67. package/build-types/actions/delete-post.d.ts.map +1 -1
  68. package/build-types/fields/featured-image/featured-image-edit.d.ts +7 -0
  69. package/build-types/fields/featured-image/featured-image-edit.d.ts.map +1 -0
  70. package/build-types/fields/featured-image/featured-image-view.d.ts +7 -0
  71. package/build-types/fields/featured-image/featured-image-view.d.ts.map +1 -0
  72. package/build-types/fields/featured-image/index.d.ts +11 -0
  73. package/build-types/fields/featured-image/index.d.ts.map +1 -0
  74. package/build-types/fields/index.d.ts +3 -0
  75. package/build-types/fields/index.d.ts.map +1 -1
  76. package/build-types/fields/parent/index.d.ts +14 -0
  77. package/build-types/fields/parent/index.d.ts.map +1 -0
  78. package/build-types/fields/parent/parent-edit.d.ts +9 -0
  79. package/build-types/fields/parent/parent-edit.d.ts.map +1 -0
  80. package/build-types/fields/parent/parent-view.d.ts +7 -0
  81. package/build-types/fields/parent/parent-view.d.ts.map +1 -0
  82. package/build-types/fields/parent/utils.d.ts +6 -0
  83. package/build-types/fields/parent/utils.d.ts.map +1 -0
  84. package/build-types/fields/slug/index.d.ts +11 -0
  85. package/build-types/fields/slug/index.d.ts.map +1 -0
  86. package/build-types/fields/slug/slug-edit.d.ts +8 -0
  87. package/build-types/fields/slug/slug-edit.d.ts.map +1 -0
  88. package/build-types/fields/slug/slug-view.d.ts +9 -0
  89. package/build-types/fields/slug/slug-view.d.ts.map +1 -0
  90. package/build-types/types.d.ts +2 -0
  91. package/build-types/types.d.ts.map +1 -1
  92. package/package.json +26 -22
  93. package/src/actions/delete-post.tsx +8 -5
  94. package/src/actions/duplicate-post.tsx +2 -2
  95. package/src/actions/view-post-revisions.tsx +1 -1
  96. package/src/fields/featured-image/featured-image-edit.tsx +122 -0
  97. package/src/fields/featured-image/featured-image-view.tsx +38 -0
  98. package/src/fields/featured-image/index.ts +24 -0
  99. package/src/fields/featured-image/style.scss +95 -0
  100. package/src/fields/index.ts +3 -0
  101. package/src/fields/parent/index.ts +27 -0
  102. package/src/fields/parent/parent-edit.tsx +348 -0
  103. package/src/fields/parent/parent-view.tsx +33 -0
  104. package/src/fields/parent/utils.ts +18 -0
  105. package/src/fields/slug/index.ts +23 -0
  106. package/src/fields/slug/slug-edit.tsx +156 -0
  107. package/src/fields/slug/slug-view.tsx +26 -0
  108. package/src/fields/slug/style.scss +22 -0
  109. package/src/mutation/index.ts +3 -3
  110. package/src/styles.scss +1 -0
  111. package/src/types.ts +2 -0
  112. package/tsconfig.json +3 -1
  113. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,23 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import type { Field } from '@wordpress/dataviews';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import type { BasePost } from '../../types';
10
+ import { __ } from '@wordpress/i18n';
11
+ import SlugEdit from './slug-edit';
12
+ import SlugView from './slug-view';
13
+
14
+ const slugField: Field< BasePost > = {
15
+ id: 'slug',
16
+ type: 'text',
17
+ label: __( 'Slug' ),
18
+ getValue: ( { item } ) => item.slug,
19
+ Edit: SlugEdit,
20
+ render: SlugView,
21
+ };
22
+
23
+ export default slugField;
@@ -0,0 +1,156 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ Button,
6
+ ExternalLink,
7
+ __experimentalInputControl as InputControl,
8
+ __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
9
+ __experimentalVStack as VStack,
10
+ } from '@wordpress/components';
11
+ import { copySmall } from '@wordpress/icons';
12
+ import { useCopyToClipboard, useInstanceId } from '@wordpress/compose';
13
+ import { useDispatch } from '@wordpress/data';
14
+ import { useCallback, useEffect, useRef } from '@wordpress/element';
15
+ import { store as noticesStore } from '@wordpress/notices';
16
+ import { safeDecodeURIComponent } from '@wordpress/url';
17
+ import type { DataFormControlProps } from '@wordpress/dataviews';
18
+ import { __ } from '@wordpress/i18n';
19
+
20
+ /**
21
+ * Internal dependencies
22
+ */
23
+ import type { BasePost } from '../../types';
24
+
25
+ const SlugEdit = ( {
26
+ field,
27
+ onChange,
28
+ data,
29
+ }: DataFormControlProps< BasePost > ) => {
30
+ const { id } = field;
31
+
32
+ const slug = field.getValue( { item: data } ) ?? '';
33
+ const permalinkTemplate = data.permalink_template || '';
34
+ const PERMALINK_POSTNAME_REGEX = /%(?:postname|pagename)%/;
35
+ const [ prefix, suffix ] = permalinkTemplate.split(
36
+ PERMALINK_POSTNAME_REGEX
37
+ );
38
+ const permalinkPrefix = prefix;
39
+ const permalinkSuffix = suffix;
40
+ const isEditable = PERMALINK_POSTNAME_REGEX.test( permalinkTemplate );
41
+ const originalSlugRef = useRef( slug );
42
+ const slugToDisplay = slug || originalSlugRef.current;
43
+ const permalink = isEditable
44
+ ? `${ permalinkPrefix }${ slugToDisplay }${ permalinkSuffix }`
45
+ : safeDecodeURIComponent( data.link || '' );
46
+
47
+ useEffect( () => {
48
+ if ( slug && originalSlugRef.current === undefined ) {
49
+ originalSlugRef.current = slug;
50
+ }
51
+ }, [ slug ] );
52
+
53
+ const onChangeControl = useCallback(
54
+ ( newValue?: string ) =>
55
+ onChange( {
56
+ [ id ]: newValue,
57
+ } ),
58
+ [ id, onChange ]
59
+ );
60
+
61
+ const { createNotice } = useDispatch( noticesStore );
62
+
63
+ const copyButtonRef = useCopyToClipboard( permalink, () => {
64
+ createNotice( 'info', __( 'Copied Permalink to clipboard.' ), {
65
+ isDismissible: true,
66
+ type: 'snackbar',
67
+ } );
68
+ } );
69
+
70
+ const postUrlSlugDescriptionId =
71
+ 'editor-post-url__slug-description-' + useInstanceId( SlugEdit );
72
+
73
+ return (
74
+ <fieldset className="fields-controls__slug">
75
+ { isEditable && (
76
+ <VStack>
77
+ <VStack spacing="0px">
78
+ <span>
79
+ { __(
80
+ 'Customize the last part of the Permalink.'
81
+ ) }
82
+ </span>
83
+ <ExternalLink href="https://wordpress.org/documentation/article/page-post-settings-sidebar/#permalink">
84
+ { __( 'Learn more' ) }
85
+ </ExternalLink>
86
+ </VStack>
87
+ <InputControl
88
+ __next40pxDefaultSize
89
+ prefix={
90
+ <InputControlPrefixWrapper>
91
+ /
92
+ </InputControlPrefixWrapper>
93
+ }
94
+ suffix={
95
+ <Button
96
+ __next40pxDefaultSize
97
+ icon={ copySmall }
98
+ ref={ copyButtonRef }
99
+ label={ __( 'Copy' ) }
100
+ />
101
+ }
102
+ label={ __( 'Link' ) }
103
+ hideLabelFromVision
104
+ value={ slug }
105
+ autoComplete="off"
106
+ spellCheck="false"
107
+ type="text"
108
+ className="fields-controls__slug-input"
109
+ onChange={ ( newValue?: string ) => {
110
+ onChangeControl( newValue );
111
+ } }
112
+ onBlur={ () => {
113
+ if ( slug === '' ) {
114
+ onChangeControl( originalSlugRef.current );
115
+ }
116
+ } }
117
+ aria-describedby={ postUrlSlugDescriptionId }
118
+ help={
119
+ <>
120
+ <p className="fields-controls__slug-help">
121
+ <span className="fields-controls__slug-help-visual-label">
122
+ { __( 'Permalink:' ) }
123
+ </span>
124
+ <ExternalLink
125
+ className="fields-controls__slug-help-link"
126
+ href={ permalink }
127
+ >
128
+ <span className="fields-controls__slug-help-prefix">
129
+ { permalinkPrefix }
130
+ </span>
131
+ <span className="fields-controls__slug-help-slug">
132
+ { slugToDisplay }
133
+ </span>
134
+ <span className="fields-controls__slug-help-suffix">
135
+ { permalinkSuffix }
136
+ </span>
137
+ </ExternalLink>
138
+ </p>
139
+ </>
140
+ }
141
+ />
142
+ </VStack>
143
+ ) }
144
+ { ! isEditable && (
145
+ <ExternalLink
146
+ className="fields-controls__slug-help"
147
+ href={ permalink }
148
+ >
149
+ { permalink }
150
+ </ExternalLink>
151
+ ) }
152
+ </fieldset>
153
+ );
154
+ };
155
+
156
+ export default SlugEdit;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useEffect, useRef } from '@wordpress/element';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import type { BasePost } from '../../types';
10
+
11
+ const SlugView = ( { item }: { item: BasePost } ) => {
12
+ const slug = item.slug;
13
+ const originalSlugRef = useRef( slug );
14
+
15
+ useEffect( () => {
16
+ if ( slug && originalSlugRef.current === undefined ) {
17
+ originalSlugRef.current = slug;
18
+ }
19
+ }, [ slug ] );
20
+
21
+ const slugToDisplay = slug || originalSlugRef.current;
22
+
23
+ return `/${ slugToDisplay ?? '' }`;
24
+ };
25
+
26
+ export default SlugView;
@@ -0,0 +1,22 @@
1
+ .fields-controls__slug {
2
+ .fields-controls__slug-external-icon {
3
+ margin-left: 5ch;
4
+ }
5
+
6
+ .fields-controls__slug-input input.components-input-control__input {
7
+ padding-inline-start: 0 !important;
8
+ }
9
+
10
+ .fields-controls__slug-help-link {
11
+ word-break: break-word;
12
+ }
13
+
14
+ .fields-controls__slug-help {
15
+ display: flex;
16
+ flex-direction: column;
17
+
18
+ .fields-controls__slug-help-slug {
19
+ font-weight: 600;
20
+ }
21
+ }
22
+ }
@@ -10,9 +10,9 @@ import { dispatch } from '@wordpress/data';
10
10
  */
11
11
  import type { CoreDataError, Post } from '../types';
12
12
 
13
- const getErrorMessagesFromPromises = < T >(
13
+ function getErrorMessagesFromPromises< T >(
14
14
  allSettledResults: PromiseSettledResult< T >[]
15
- ) => {
15
+ ) {
16
16
  const errorMessages = new Set< string >();
17
17
  // If there was at lease one failure.
18
18
  if ( allSettledResults.length === 1 ) {
@@ -36,7 +36,7 @@ const getErrorMessagesFromPromises = < T >(
36
36
  }
37
37
  }
38
38
  return errorMessages;
39
- };
39
+ }
40
40
 
41
41
  export type NoticeSettings< T extends Post > = {
42
42
  success: {
@@ -0,0 +1 @@
1
+ @import "./fields/slug/style.scss";
package/src/types.ts CHANGED
@@ -35,6 +35,8 @@ export interface BasePost extends CommonPost {
35
35
  menu_order?: number;
36
36
  ping_status?: 'open' | 'closed';
37
37
  link?: string;
38
+ slug?: string;
39
+ permalink_template?: string;
38
40
  }
39
41
 
40
42
  export interface Template extends CommonPost {
package/tsconfig.json CHANGED
@@ -23,7 +23,9 @@
23
23
  { "path": "../blob" },
24
24
  { "path": "../core-data" },
25
25
  { "path": "../hooks" },
26
- { "path": "../html-entities" }
26
+ { "path": "../html-entities" },
27
+ { "path": "../media-utils" },
28
+ { "path": "../router" }
27
29
  ],
28
30
  "include": [ "src" ]
29
31
  }