@atlaskit/editor-toolbar-model 0.0.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/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ # @atlaskit/editor-toolbar-model
package/LICENSE.md ADDED
@@ -0,0 +1,11 @@
1
+ Copyright 2023 Atlassian Pty Ltd
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
4
+ compliance with the License. You may obtain a copy of the License at
5
+
6
+ http://www.apache.org/licenses/LICENSE-2.0
7
+
8
+ Unless required by applicable law or agreed to in writing, software distributed under the License is
9
+ distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10
+ implied. See the License for the specific language governing permissions and limitations under the
11
+ License.
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Editor Toolbar Mode
2
+
3
+ This package enforces a toolbar structure by exposing a simple registry API for components, and providing a react based toolbar model used for rendering an entire toolbar.
4
+
5
+ ## Usage
6
+
7
+ Register toolbar components
8
+
9
+ ```ts
10
+ import { createComponentRegistry, type RegisterToolbar } from '@atlaskit/editor-toolbar-model';
11
+
12
+ const registry = createComponentRegistry()
13
+
14
+ registry.register([
15
+ {
16
+ type: 'toolbar'
17
+ key: 'inline-toolbar'
18
+ } as RegisterToolbar
19
+ ])
20
+
21
+ ```
22
+
23
+ Get all registered components
24
+
25
+ ```ts
26
+ import { createComponentRegistry } from '@atlaskit/editor-toolbar-model';
27
+
28
+ const { components } = registry;
29
+
30
+ console.log(components)
31
+
32
+ ```
33
+
34
+ Process all toolbar components
35
+
36
+ ```ts
37
+ import { ToolbarModel, createComponentRegistry } from '@atlaskit/editor-toolbar-model';
38
+
39
+
40
+ return <ToolbarModel components={registry.components} item={{ type: 'toolbar', key: 'inline-toolbar' }} />
41
+
42
+ ```
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.createComponentRegistry = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ /**
10
+ * Create a simple registry for toolbar components.
11
+ *
12
+ * @returns A registry object with a `register` method and a `components` array.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const registry = createToolbarRegistry();
17
+ *
18
+ * registry.register([
19
+ * {
20
+ * type: 'toolbar',
21
+ * key: 'primary-toolbar',
22
+ * component: ({ children }) => <div>{children}</div>,
23
+ * },
24
+ * {
25
+ * type: 'section',
26
+ * key: 'section-1',
27
+ * rank: 1,
28
+ * parents: [{ type: 'toolbar', key: 'primary-toolbar' }],
29
+ * component: ({ children }) => <div>{children}</div>,
30
+ * },
31
+ * {
32
+ * type: 'group',
33
+ * key: 'group-1',
34
+ * rank: 1,
35
+ * parents: [{ type: 'section', key: 'section-1' }],
36
+ * component: ({ children }) => <div>{children}</div>,
37
+ * },
38
+ * ]);
39
+ */
40
+ var createComponentRegistry = exports.createComponentRegistry = function createComponentRegistry() {
41
+ var components = [];
42
+ var register = function register(newComponents) {
43
+ components.push.apply(components, (0, _toConsumableArray2.default)(newComponents));
44
+ };
45
+ return {
46
+ register: register,
47
+ components: components
48
+ };
49
+ };
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "ToolbarModelRenderer", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _toolbarModelRenderer.ToolbarModelRenderer;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "createComponentRegistry", {
13
+ enumerable: true,
14
+ get: function get() {
15
+ return _createRegistry.createComponentRegistry;
16
+ }
17
+ });
18
+ var _toolbarModelRenderer = require("./ui/toolbar-model-renderer");
19
+ var _createRegistry = require("./create-registry");
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.ToolbarModelRenderer = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _react = _interopRequireDefault(require("react"));
10
+ var NoOp = function NoOp(props) {
11
+ return null;
12
+ };
13
+ var isSection = function isSection(component) {
14
+ return component.type === 'section';
15
+ };
16
+ var isGroup = function isGroup(component) {
17
+ return component.type === 'group';
18
+ };
19
+ var isToolbarItem = function isToolbarItem(component) {
20
+ return component.type === 'button' || component.type === 'menu';
21
+ };
22
+ var isToolbarMenuSection = function isToolbarMenuSection(component) {
23
+ return component.type === 'menu-section';
24
+ };
25
+ var isToolbarMenuItem = function isToolbarMenuItem(component) {
26
+ return component.type === 'menu-item' || component.type === 'menu-section';
27
+ };
28
+ var getSortedChildren = function getSortedChildren(components, parentKey) {
29
+ return components.filter(function (component) {
30
+ return component.parents.some(function (parent) {
31
+ return parent.key === parentKey;
32
+ });
33
+ }).sort(function (a, b) {
34
+ var _a$parents$find, _b$parents$find;
35
+ return (((_a$parents$find = a.parents.find(function (p) {
36
+ return p.key === parentKey;
37
+ })) === null || _a$parents$find === void 0 ? void 0 : _a$parents$find.rank) || 0) - (((_b$parents$find = b.parents.find(function (p) {
38
+ return p.key === parentKey;
39
+ })) === null || _b$parents$find === void 0 ? void 0 : _b$parents$find.rank) || 0);
40
+ });
41
+ };
42
+ var ToolbarModelRenderer = exports.ToolbarModelRenderer = function ToolbarModelRenderer(_ref) {
43
+ var toolbar = _ref.toolbar,
44
+ components = _ref.components,
45
+ fallbacks = _ref.fallbacks;
46
+ var sections = getSortedChildren(components.filter(isSection), toolbar.key);
47
+ var groups = components.filter(isGroup);
48
+ var toolbarItems = components.filter(isToolbarItem);
49
+ var menuSections = components.filter(isToolbarMenuSection);
50
+ var menuItems = components.filter(isToolbarMenuItem);
51
+ var renderToolbarItem = function renderToolbarItem(_ref2) {
52
+ var item = _ref2.item,
53
+ index = _ref2.index,
54
+ groupLocation = _ref2.groupLocation,
55
+ parents = _ref2.parents;
56
+ if (item.type === 'menu') {
57
+ var menuComponents = getSortedChildren(menuSections, item.key);
58
+ if (menuComponents.length === 0) {
59
+ return null;
60
+ }
61
+ var Menu = item.component || NoOp;
62
+ return /*#__PURE__*/_react.default.createElement(Menu, {
63
+ key: item.key,
64
+ groupLocation: groupLocation,
65
+ parents: parents
66
+ }, menuComponents.map(function (menuSection) {
67
+ var menuItemsInSection = getSortedChildren(menuItems, menuSection.key);
68
+ var MenuSection = menuSection.component || fallbacks.menuSection;
69
+ return /*#__PURE__*/_react.default.createElement(MenuSection, {
70
+ key: menuSection.key,
71
+ parents: [].concat((0, _toConsumableArray2.default)(parents), [{
72
+ key: item.key,
73
+ type: item.type
74
+ }])
75
+ }, menuItemsInSection.map(function (menuItem) {
76
+ var MenuItem = menuItem.component || NoOp;
77
+ return /*#__PURE__*/_react.default.createElement(MenuItem, {
78
+ key: menuItem.key,
79
+ parents: [].concat((0, _toConsumableArray2.default)(parents), [{
80
+ key: item.key,
81
+ type: item.type
82
+ }, {
83
+ key: menuSection.key,
84
+ type: menuSection.type
85
+ }])
86
+ });
87
+ }));
88
+ }));
89
+ }
90
+ var Button = item.component || NoOp;
91
+ return /*#__PURE__*/_react.default.createElement(Button, {
92
+ key: item.key,
93
+ groupLocation: groupLocation,
94
+ parents: parents
95
+ });
96
+ };
97
+ var renderGroup = function renderGroup(group, parents) {
98
+ var groupItems = getSortedChildren(toolbarItems, group.key);
99
+ if (groupItems.length === 0) {
100
+ return null;
101
+ }
102
+ var Group = group.component || fallbacks.group;
103
+ return /*#__PURE__*/_react.default.createElement(Group, {
104
+ key: group.key,
105
+ parents: parents
106
+ }, groupItems.map(function (item, index) {
107
+ var isSingleItem = groupItems.length === 1;
108
+ var groupLocation = isSingleItem ? undefined : index === 0 ? 'start' : index === groupItems.length - 1 ? 'end' : 'middle';
109
+ return renderToolbarItem({
110
+ item: item,
111
+ index: index,
112
+ groupLocation: groupLocation,
113
+ parents: [].concat((0, _toConsumableArray2.default)(parents), [{
114
+ key: group.key,
115
+ type: group.type
116
+ }])
117
+ });
118
+ }));
119
+ };
120
+ var renderSection = function renderSection(section) {
121
+ var sectionGroups = getSortedChildren(groups, section.key);
122
+ var Section = section.component || fallbacks.section;
123
+ var parents = [{
124
+ key: toolbar.key,
125
+ type: toolbar.type
126
+ }];
127
+ return /*#__PURE__*/_react.default.createElement(Section, {
128
+ key: section.key,
129
+ parents: parents
130
+ }, sectionGroups.map(function (group) {
131
+ return renderGroup(group, [].concat(parents, [{
132
+ key: section.key,
133
+ type: section.type
134
+ }]));
135
+ }));
136
+ };
137
+ var ToolbarComponent = toolbar.component || NoOp;
138
+ return /*#__PURE__*/_react.default.createElement(ToolbarComponent, null, sections.map(renderSection));
139
+ };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Create a simple registry for toolbar components.
3
+ *
4
+ * @returns A registry object with a `register` method and a `components` array.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * const registry = createToolbarRegistry();
9
+ *
10
+ * registry.register([
11
+ * {
12
+ * type: 'toolbar',
13
+ * key: 'primary-toolbar',
14
+ * component: ({ children }) => <div>{children}</div>,
15
+ * },
16
+ * {
17
+ * type: 'section',
18
+ * key: 'section-1',
19
+ * rank: 1,
20
+ * parents: [{ type: 'toolbar', key: 'primary-toolbar' }],
21
+ * component: ({ children }) => <div>{children}</div>,
22
+ * },
23
+ * {
24
+ * type: 'group',
25
+ * key: 'group-1',
26
+ * rank: 1,
27
+ * parents: [{ type: 'section', key: 'section-1' }],
28
+ * component: ({ children }) => <div>{children}</div>,
29
+ * },
30
+ * ]);
31
+ */
32
+ export const createComponentRegistry = () => {
33
+ const components = [];
34
+ const register = newComponents => {
35
+ components.push(...newComponents);
36
+ };
37
+ return {
38
+ register,
39
+ components
40
+ };
41
+ };
@@ -0,0 +1,4 @@
1
+ /* eslint-disable @atlaskit/editor/no-re-export */
2
+
3
+ export { ToolbarModelRenderer } from './ui/toolbar-model-renderer';
4
+ export { createComponentRegistry } from './create-registry';
File without changes
@@ -0,0 +1,119 @@
1
+ import React from 'react';
2
+ const NoOp = props => null;
3
+ const isSection = component => {
4
+ return component.type === 'section';
5
+ };
6
+ const isGroup = component => {
7
+ return component.type === 'group';
8
+ };
9
+ const isToolbarItem = component => {
10
+ return component.type === 'button' || component.type === 'menu';
11
+ };
12
+ const isToolbarMenuSection = component => {
13
+ return component.type === 'menu-section';
14
+ };
15
+ const isToolbarMenuItem = component => {
16
+ return component.type === 'menu-item' || component.type === 'menu-section';
17
+ };
18
+ const getSortedChildren = (components, parentKey) => components.filter(component => component.parents.some(parent => parent.key === parentKey)).sort((a, b) => {
19
+ var _a$parents$find, _b$parents$find;
20
+ return (((_a$parents$find = a.parents.find(p => p.key === parentKey)) === null || _a$parents$find === void 0 ? void 0 : _a$parents$find.rank) || 0) - (((_b$parents$find = b.parents.find(p => p.key === parentKey)) === null || _b$parents$find === void 0 ? void 0 : _b$parents$find.rank) || 0);
21
+ });
22
+ export const ToolbarModelRenderer = ({
23
+ toolbar,
24
+ components,
25
+ fallbacks
26
+ }) => {
27
+ const sections = getSortedChildren(components.filter(isSection), toolbar.key);
28
+ const groups = components.filter(isGroup);
29
+ const toolbarItems = components.filter(isToolbarItem);
30
+ const menuSections = components.filter(isToolbarMenuSection);
31
+ const menuItems = components.filter(isToolbarMenuItem);
32
+ const renderToolbarItem = ({
33
+ item,
34
+ index,
35
+ groupLocation,
36
+ parents
37
+ }) => {
38
+ if (item.type === 'menu') {
39
+ const menuComponents = getSortedChildren(menuSections, item.key);
40
+ if (menuComponents.length === 0) {
41
+ return null;
42
+ }
43
+ const Menu = item.component || NoOp;
44
+ return /*#__PURE__*/React.createElement(Menu, {
45
+ key: item.key,
46
+ groupLocation: groupLocation,
47
+ parents: parents
48
+ }, menuComponents.map(menuSection => {
49
+ const menuItemsInSection = getSortedChildren(menuItems, menuSection.key);
50
+ const MenuSection = menuSection.component || fallbacks.menuSection;
51
+ return /*#__PURE__*/React.createElement(MenuSection, {
52
+ key: menuSection.key,
53
+ parents: [...parents, {
54
+ key: item.key,
55
+ type: item.type
56
+ }]
57
+ }, menuItemsInSection.map(menuItem => {
58
+ const MenuItem = menuItem.component || NoOp;
59
+ return /*#__PURE__*/React.createElement(MenuItem, {
60
+ key: menuItem.key,
61
+ parents: [...parents, {
62
+ key: item.key,
63
+ type: item.type
64
+ }, {
65
+ key: menuSection.key,
66
+ type: menuSection.type
67
+ }]
68
+ });
69
+ }));
70
+ }));
71
+ }
72
+ const Button = item.component || NoOp;
73
+ return /*#__PURE__*/React.createElement(Button, {
74
+ key: item.key,
75
+ groupLocation: groupLocation,
76
+ parents: parents
77
+ });
78
+ };
79
+ const renderGroup = (group, parents) => {
80
+ const groupItems = getSortedChildren(toolbarItems, group.key);
81
+ if (groupItems.length === 0) {
82
+ return null;
83
+ }
84
+ const Group = group.component || fallbacks.group;
85
+ return /*#__PURE__*/React.createElement(Group, {
86
+ key: group.key,
87
+ parents: parents
88
+ }, groupItems.map((item, index) => {
89
+ const isSingleItem = groupItems.length === 1;
90
+ const groupLocation = isSingleItem ? undefined : index === 0 ? 'start' : index === groupItems.length - 1 ? 'end' : 'middle';
91
+ return renderToolbarItem({
92
+ item,
93
+ index,
94
+ groupLocation,
95
+ parents: [...parents, {
96
+ key: group.key,
97
+ type: group.type
98
+ }]
99
+ });
100
+ }));
101
+ };
102
+ const renderSection = section => {
103
+ const sectionGroups = getSortedChildren(groups, section.key);
104
+ const Section = section.component || fallbacks.section;
105
+ const parents = [{
106
+ key: toolbar.key,
107
+ type: toolbar.type
108
+ }];
109
+ return /*#__PURE__*/React.createElement(Section, {
110
+ key: section.key,
111
+ parents: parents
112
+ }, sectionGroups.map(group => renderGroup(group, [...parents, {
113
+ key: section.key,
114
+ type: section.type
115
+ }])));
116
+ };
117
+ const ToolbarComponent = toolbar.component || NoOp;
118
+ return /*#__PURE__*/React.createElement(ToolbarComponent, null, sections.map(renderSection));
119
+ };
@@ -0,0 +1,42 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ /**
3
+ * Create a simple registry for toolbar components.
4
+ *
5
+ * @returns A registry object with a `register` method and a `components` array.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const registry = createToolbarRegistry();
10
+ *
11
+ * registry.register([
12
+ * {
13
+ * type: 'toolbar',
14
+ * key: 'primary-toolbar',
15
+ * component: ({ children }) => <div>{children}</div>,
16
+ * },
17
+ * {
18
+ * type: 'section',
19
+ * key: 'section-1',
20
+ * rank: 1,
21
+ * parents: [{ type: 'toolbar', key: 'primary-toolbar' }],
22
+ * component: ({ children }) => <div>{children}</div>,
23
+ * },
24
+ * {
25
+ * type: 'group',
26
+ * key: 'group-1',
27
+ * rank: 1,
28
+ * parents: [{ type: 'section', key: 'section-1' }],
29
+ * component: ({ children }) => <div>{children}</div>,
30
+ * },
31
+ * ]);
32
+ */
33
+ export var createComponentRegistry = function createComponentRegistry() {
34
+ var components = [];
35
+ var register = function register(newComponents) {
36
+ components.push.apply(components, _toConsumableArray(newComponents));
37
+ };
38
+ return {
39
+ register: register,
40
+ components: components
41
+ };
42
+ };
@@ -0,0 +1,4 @@
1
+ /* eslint-disable @atlaskit/editor/no-re-export */
2
+
3
+ export { ToolbarModelRenderer } from './ui/toolbar-model-renderer';
4
+ export { createComponentRegistry } from './create-registry';
File without changes
@@ -0,0 +1,132 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import React from 'react';
3
+ var NoOp = function NoOp(props) {
4
+ return null;
5
+ };
6
+ var isSection = function isSection(component) {
7
+ return component.type === 'section';
8
+ };
9
+ var isGroup = function isGroup(component) {
10
+ return component.type === 'group';
11
+ };
12
+ var isToolbarItem = function isToolbarItem(component) {
13
+ return component.type === 'button' || component.type === 'menu';
14
+ };
15
+ var isToolbarMenuSection = function isToolbarMenuSection(component) {
16
+ return component.type === 'menu-section';
17
+ };
18
+ var isToolbarMenuItem = function isToolbarMenuItem(component) {
19
+ return component.type === 'menu-item' || component.type === 'menu-section';
20
+ };
21
+ var getSortedChildren = function getSortedChildren(components, parentKey) {
22
+ return components.filter(function (component) {
23
+ return component.parents.some(function (parent) {
24
+ return parent.key === parentKey;
25
+ });
26
+ }).sort(function (a, b) {
27
+ var _a$parents$find, _b$parents$find;
28
+ return (((_a$parents$find = a.parents.find(function (p) {
29
+ return p.key === parentKey;
30
+ })) === null || _a$parents$find === void 0 ? void 0 : _a$parents$find.rank) || 0) - (((_b$parents$find = b.parents.find(function (p) {
31
+ return p.key === parentKey;
32
+ })) === null || _b$parents$find === void 0 ? void 0 : _b$parents$find.rank) || 0);
33
+ });
34
+ };
35
+ export var ToolbarModelRenderer = function ToolbarModelRenderer(_ref) {
36
+ var toolbar = _ref.toolbar,
37
+ components = _ref.components,
38
+ fallbacks = _ref.fallbacks;
39
+ var sections = getSortedChildren(components.filter(isSection), toolbar.key);
40
+ var groups = components.filter(isGroup);
41
+ var toolbarItems = components.filter(isToolbarItem);
42
+ var menuSections = components.filter(isToolbarMenuSection);
43
+ var menuItems = components.filter(isToolbarMenuItem);
44
+ var renderToolbarItem = function renderToolbarItem(_ref2) {
45
+ var item = _ref2.item,
46
+ index = _ref2.index,
47
+ groupLocation = _ref2.groupLocation,
48
+ parents = _ref2.parents;
49
+ if (item.type === 'menu') {
50
+ var menuComponents = getSortedChildren(menuSections, item.key);
51
+ if (menuComponents.length === 0) {
52
+ return null;
53
+ }
54
+ var Menu = item.component || NoOp;
55
+ return /*#__PURE__*/React.createElement(Menu, {
56
+ key: item.key,
57
+ groupLocation: groupLocation,
58
+ parents: parents
59
+ }, menuComponents.map(function (menuSection) {
60
+ var menuItemsInSection = getSortedChildren(menuItems, menuSection.key);
61
+ var MenuSection = menuSection.component || fallbacks.menuSection;
62
+ return /*#__PURE__*/React.createElement(MenuSection, {
63
+ key: menuSection.key,
64
+ parents: [].concat(_toConsumableArray(parents), [{
65
+ key: item.key,
66
+ type: item.type
67
+ }])
68
+ }, menuItemsInSection.map(function (menuItem) {
69
+ var MenuItem = menuItem.component || NoOp;
70
+ return /*#__PURE__*/React.createElement(MenuItem, {
71
+ key: menuItem.key,
72
+ parents: [].concat(_toConsumableArray(parents), [{
73
+ key: item.key,
74
+ type: item.type
75
+ }, {
76
+ key: menuSection.key,
77
+ type: menuSection.type
78
+ }])
79
+ });
80
+ }));
81
+ }));
82
+ }
83
+ var Button = item.component || NoOp;
84
+ return /*#__PURE__*/React.createElement(Button, {
85
+ key: item.key,
86
+ groupLocation: groupLocation,
87
+ parents: parents
88
+ });
89
+ };
90
+ var renderGroup = function renderGroup(group, parents) {
91
+ var groupItems = getSortedChildren(toolbarItems, group.key);
92
+ if (groupItems.length === 0) {
93
+ return null;
94
+ }
95
+ var Group = group.component || fallbacks.group;
96
+ return /*#__PURE__*/React.createElement(Group, {
97
+ key: group.key,
98
+ parents: parents
99
+ }, groupItems.map(function (item, index) {
100
+ var isSingleItem = groupItems.length === 1;
101
+ var groupLocation = isSingleItem ? undefined : index === 0 ? 'start' : index === groupItems.length - 1 ? 'end' : 'middle';
102
+ return renderToolbarItem({
103
+ item: item,
104
+ index: index,
105
+ groupLocation: groupLocation,
106
+ parents: [].concat(_toConsumableArray(parents), [{
107
+ key: group.key,
108
+ type: group.type
109
+ }])
110
+ });
111
+ }));
112
+ };
113
+ var renderSection = function renderSection(section) {
114
+ var sectionGroups = getSortedChildren(groups, section.key);
115
+ var Section = section.component || fallbacks.section;
116
+ var parents = [{
117
+ key: toolbar.key,
118
+ type: toolbar.type
119
+ }];
120
+ return /*#__PURE__*/React.createElement(Section, {
121
+ key: section.key,
122
+ parents: parents
123
+ }, sectionGroups.map(function (group) {
124
+ return renderGroup(group, [].concat(parents, [{
125
+ key: section.key,
126
+ type: section.type
127
+ }]));
128
+ }));
129
+ };
130
+ var ToolbarComponent = toolbar.component || NoOp;
131
+ return /*#__PURE__*/React.createElement(ToolbarComponent, null, sections.map(renderSection));
132
+ };
@@ -0,0 +1,36 @@
1
+ import type { RegisterComponent } from './types';
2
+ /**
3
+ * Create a simple registry for toolbar components.
4
+ *
5
+ * @returns A registry object with a `register` method and a `components` array.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const registry = createToolbarRegistry();
10
+ *
11
+ * registry.register([
12
+ * {
13
+ * type: 'toolbar',
14
+ * key: 'primary-toolbar',
15
+ * component: ({ children }) => <div>{children}</div>,
16
+ * },
17
+ * {
18
+ * type: 'section',
19
+ * key: 'section-1',
20
+ * rank: 1,
21
+ * parents: [{ type: 'toolbar', key: 'primary-toolbar' }],
22
+ * component: ({ children }) => <div>{children}</div>,
23
+ * },
24
+ * {
25
+ * type: 'group',
26
+ * key: 'group-1',
27
+ * rank: 1,
28
+ * parents: [{ type: 'section', key: 'section-1' }],
29
+ * component: ({ children }) => <div>{children}</div>,
30
+ * },
31
+ * ]);
32
+ */
33
+ export declare const createComponentRegistry: () => {
34
+ register: (newComponents: RegisterComponent[]) => void;
35
+ components: RegisterComponent[];
36
+ };
@@ -0,0 +1,3 @@
1
+ export { ToolbarModelRenderer } from './ui/toolbar-model-renderer';
2
+ export type { ToolbarMenuComponent, ToolbarButtonComponent, ToolbarMenuItemComponent, ToolbarGroupComponent, RegisterToolbar, RegisterToolbarSection, RegisterToolbarGroup, RegisterToolbarButton, RegisterToolbarMenu, RegisterToolbarMenuSection, RegisterToolbarMenuItem, RegisterComponent, } from './types';
3
+ export { createComponentRegistry } from './create-registry';
@@ -0,0 +1,92 @@
1
+ /// <reference types="react" />
2
+ type WithRank<T> = T & {
3
+ rank: number;
4
+ };
5
+ type Parents<T> = Array<WithRank<T>>;
6
+ type ComponentType = Toolbar | ToolbarSection | ToolbarGroup | ToolbarButton | ToolbarMenu | ToolbarMenuSection | ToolbarMenuItem;
7
+ export type ComponentTypes = Array<ComponentType>;
8
+ type CommonComponentProps = {
9
+ /**
10
+ * Array of parent information including both keys and types
11
+ * Ordered from immediate parent to root parent
12
+ */
13
+ parents: ComponentTypes;
14
+ };
15
+ export type ToolbarButtonGroupLocation = 'start' | 'middle' | 'end';
16
+ export type ToolbarComponent = (props: {
17
+ children: React.ReactNode;
18
+ }) => React.ReactNode;
19
+ export type ToolbarSectionComponent = (props: {
20
+ children: React.ReactNode;
21
+ } & CommonComponentProps) => React.ReactNode;
22
+ export type ToolbarGroupComponent = (props: {
23
+ children: React.ReactNode;
24
+ } & CommonComponentProps) => React.ReactNode;
25
+ export type ToolbarMenuComponent = (props: {
26
+ groupLocation?: ToolbarButtonGroupLocation;
27
+ children: React.ReactNode;
28
+ } & CommonComponentProps) => React.ReactNode;
29
+ export type ToolbarButtonComponent = (props: {
30
+ groupLocation?: ToolbarButtonGroupLocation;
31
+ } & CommonComponentProps) => React.ReactNode;
32
+ export type ToolbarMenuSectionComponent = (props: {
33
+ children: React.ReactNode;
34
+ } & CommonComponentProps) => React.ReactNode;
35
+ export type ToolbarMenuItemComponent = (props: {} & CommonComponentProps) => React.ReactNode;
36
+ type Toolbar = {
37
+ type: 'toolbar';
38
+ key: string;
39
+ };
40
+ type ToolbarSection = {
41
+ key: string;
42
+ type: 'section';
43
+ };
44
+ type ToolbarGroup = {
45
+ key: string;
46
+ type: 'group';
47
+ };
48
+ type ToolbarButton = {
49
+ key: string;
50
+ type: 'button';
51
+ };
52
+ type ToolbarMenuItem = {
53
+ key: string;
54
+ type: 'menu-item';
55
+ };
56
+ type ToolbarMenuSection = {
57
+ key: string;
58
+ type: 'menu-section';
59
+ };
60
+ type ToolbarMenu = {
61
+ key: string;
62
+ type: 'menu';
63
+ };
64
+ export type RegisterToolbar = Toolbar & {
65
+ component?: ToolbarComponent;
66
+ };
67
+ export type RegisterToolbarSection = ToolbarSection & {
68
+ parents: Parents<Toolbar>;
69
+ component?: ToolbarSectionComponent;
70
+ };
71
+ export type RegisterToolbarGroup = ToolbarGroup & {
72
+ parents: Parents<ToolbarSection>;
73
+ component?: ToolbarGroupComponent;
74
+ };
75
+ export type RegisterToolbarButton = ToolbarButton & {
76
+ parents: Parents<ToolbarGroup>;
77
+ component?: ToolbarButtonComponent;
78
+ };
79
+ export type RegisterToolbarMenu = ToolbarMenu & {
80
+ parents: Parents<ToolbarGroup>;
81
+ component?: ToolbarMenuComponent;
82
+ };
83
+ export type RegisterToolbarMenuSection = ToolbarMenuSection & {
84
+ parents: Parents<ToolbarMenu>;
85
+ component?: ToolbarMenuSectionComponent;
86
+ };
87
+ export type RegisterToolbarMenuItem = ToolbarMenuItem & {
88
+ parents: Parents<ToolbarMenuSection>;
89
+ component?: ToolbarMenuItemComponent;
90
+ };
91
+ export type RegisterComponent = RegisterToolbar | RegisterToolbarSection | RegisterToolbarGroup | RegisterToolbarButton | RegisterToolbarMenu | RegisterToolbarMenuSection | RegisterToolbarMenuItem;
92
+ export {};
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import type { RegisterToolbar, RegisterComponent, ToolbarGroupComponent, ToolbarMenuSectionComponent, ToolbarSectionComponent } from '../../types';
3
+ type ToolbarProps = {
4
+ /**
5
+ * Toolbar component
6
+ */
7
+ toolbar: RegisterToolbar;
8
+ /**
9
+ * Every registered toolbar component
10
+ */
11
+ components: RegisterComponent[];
12
+ /**
13
+ * Fallback components used in rendering
14
+ */
15
+ fallbacks: {
16
+ group: ToolbarGroupComponent;
17
+ section: ToolbarSectionComponent;
18
+ menuSection: ToolbarMenuSectionComponent;
19
+ };
20
+ };
21
+ export declare const ToolbarModelRenderer: ({ toolbar, components, fallbacks }: ToolbarProps) => React.JSX.Element;
22
+ export {};
@@ -0,0 +1,36 @@
1
+ import type { RegisterComponent } from './types';
2
+ /**
3
+ * Create a simple registry for toolbar components.
4
+ *
5
+ * @returns A registry object with a `register` method and a `components` array.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const registry = createToolbarRegistry();
10
+ *
11
+ * registry.register([
12
+ * {
13
+ * type: 'toolbar',
14
+ * key: 'primary-toolbar',
15
+ * component: ({ children }) => <div>{children}</div>,
16
+ * },
17
+ * {
18
+ * type: 'section',
19
+ * key: 'section-1',
20
+ * rank: 1,
21
+ * parents: [{ type: 'toolbar', key: 'primary-toolbar' }],
22
+ * component: ({ children }) => <div>{children}</div>,
23
+ * },
24
+ * {
25
+ * type: 'group',
26
+ * key: 'group-1',
27
+ * rank: 1,
28
+ * parents: [{ type: 'section', key: 'section-1' }],
29
+ * component: ({ children }) => <div>{children}</div>,
30
+ * },
31
+ * ]);
32
+ */
33
+ export declare const createComponentRegistry: () => {
34
+ register: (newComponents: RegisterComponent[]) => void;
35
+ components: RegisterComponent[];
36
+ };
@@ -0,0 +1,3 @@
1
+ export { ToolbarModelRenderer } from './ui/toolbar-model-renderer';
2
+ export type { ToolbarMenuComponent, ToolbarButtonComponent, ToolbarMenuItemComponent, ToolbarGroupComponent, RegisterToolbar, RegisterToolbarSection, RegisterToolbarGroup, RegisterToolbarButton, RegisterToolbarMenu, RegisterToolbarMenuSection, RegisterToolbarMenuItem, RegisterComponent, } from './types';
3
+ export { createComponentRegistry } from './create-registry';
@@ -0,0 +1,92 @@
1
+ /// <reference types="react" />
2
+ type WithRank<T> = T & {
3
+ rank: number;
4
+ };
5
+ type Parents<T> = Array<WithRank<T>>;
6
+ type ComponentType = Toolbar | ToolbarSection | ToolbarGroup | ToolbarButton | ToolbarMenu | ToolbarMenuSection | ToolbarMenuItem;
7
+ export type ComponentTypes = Array<ComponentType>;
8
+ type CommonComponentProps = {
9
+ /**
10
+ * Array of parent information including both keys and types
11
+ * Ordered from immediate parent to root parent
12
+ */
13
+ parents: ComponentTypes;
14
+ };
15
+ export type ToolbarButtonGroupLocation = 'start' | 'middle' | 'end';
16
+ export type ToolbarComponent = (props: {
17
+ children: React.ReactNode;
18
+ }) => React.ReactNode;
19
+ export type ToolbarSectionComponent = (props: {
20
+ children: React.ReactNode;
21
+ } & CommonComponentProps) => React.ReactNode;
22
+ export type ToolbarGroupComponent = (props: {
23
+ children: React.ReactNode;
24
+ } & CommonComponentProps) => React.ReactNode;
25
+ export type ToolbarMenuComponent = (props: {
26
+ groupLocation?: ToolbarButtonGroupLocation;
27
+ children: React.ReactNode;
28
+ } & CommonComponentProps) => React.ReactNode;
29
+ export type ToolbarButtonComponent = (props: {
30
+ groupLocation?: ToolbarButtonGroupLocation;
31
+ } & CommonComponentProps) => React.ReactNode;
32
+ export type ToolbarMenuSectionComponent = (props: {
33
+ children: React.ReactNode;
34
+ } & CommonComponentProps) => React.ReactNode;
35
+ export type ToolbarMenuItemComponent = (props: {} & CommonComponentProps) => React.ReactNode;
36
+ type Toolbar = {
37
+ type: 'toolbar';
38
+ key: string;
39
+ };
40
+ type ToolbarSection = {
41
+ key: string;
42
+ type: 'section';
43
+ };
44
+ type ToolbarGroup = {
45
+ key: string;
46
+ type: 'group';
47
+ };
48
+ type ToolbarButton = {
49
+ key: string;
50
+ type: 'button';
51
+ };
52
+ type ToolbarMenuItem = {
53
+ key: string;
54
+ type: 'menu-item';
55
+ };
56
+ type ToolbarMenuSection = {
57
+ key: string;
58
+ type: 'menu-section';
59
+ };
60
+ type ToolbarMenu = {
61
+ key: string;
62
+ type: 'menu';
63
+ };
64
+ export type RegisterToolbar = Toolbar & {
65
+ component?: ToolbarComponent;
66
+ };
67
+ export type RegisterToolbarSection = ToolbarSection & {
68
+ parents: Parents<Toolbar>;
69
+ component?: ToolbarSectionComponent;
70
+ };
71
+ export type RegisterToolbarGroup = ToolbarGroup & {
72
+ parents: Parents<ToolbarSection>;
73
+ component?: ToolbarGroupComponent;
74
+ };
75
+ export type RegisterToolbarButton = ToolbarButton & {
76
+ parents: Parents<ToolbarGroup>;
77
+ component?: ToolbarButtonComponent;
78
+ };
79
+ export type RegisterToolbarMenu = ToolbarMenu & {
80
+ parents: Parents<ToolbarGroup>;
81
+ component?: ToolbarMenuComponent;
82
+ };
83
+ export type RegisterToolbarMenuSection = ToolbarMenuSection & {
84
+ parents: Parents<ToolbarMenu>;
85
+ component?: ToolbarMenuSectionComponent;
86
+ };
87
+ export type RegisterToolbarMenuItem = ToolbarMenuItem & {
88
+ parents: Parents<ToolbarMenuSection>;
89
+ component?: ToolbarMenuItemComponent;
90
+ };
91
+ export type RegisterComponent = RegisterToolbar | RegisterToolbarSection | RegisterToolbarGroup | RegisterToolbarButton | RegisterToolbarMenu | RegisterToolbarMenuSection | RegisterToolbarMenuItem;
92
+ export {};
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import type { RegisterToolbar, RegisterComponent, ToolbarGroupComponent, ToolbarMenuSectionComponent, ToolbarSectionComponent } from '../../types';
3
+ type ToolbarProps = {
4
+ /**
5
+ * Toolbar component
6
+ */
7
+ toolbar: RegisterToolbar;
8
+ /**
9
+ * Every registered toolbar component
10
+ */
11
+ components: RegisterComponent[];
12
+ /**
13
+ * Fallback components used in rendering
14
+ */
15
+ fallbacks: {
16
+ group: ToolbarGroupComponent;
17
+ section: ToolbarSectionComponent;
18
+ menuSection: ToolbarMenuSectionComponent;
19
+ };
20
+ };
21
+ export declare const ToolbarModelRenderer: ({ toolbar, components, fallbacks }: ToolbarProps) => React.JSX.Element;
22
+ export {};
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "atlassian": {
3
+ "team": "Editor: Jenga",
4
+ "releaseModel": "continuous"
5
+ },
6
+ "repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
7
+ "main": "dist/cjs/index.js",
8
+ "module": "dist/esm/index.js",
9
+ "module:es2019": "dist/es2019/index.js",
10
+ "types": "dist/types/index.d.ts",
11
+ "typesVersions": {
12
+ ">=4.5 <5.4": {
13
+ "*": [
14
+ "dist/types-ts4.5/*",
15
+ "dist/types-ts4.5/index.d.ts"
16
+ ]
17
+ }
18
+ },
19
+ "sideEffects": [
20
+ "*.compiled.css"
21
+ ],
22
+ "atlaskit:src": "src/index.ts",
23
+ "af:exports": {
24
+ ".": "./src/index.ts"
25
+ },
26
+ "dependencies": {
27
+ "@atlaskit/css": "^0.12.0",
28
+ "@atlaskit/primitives": "^14.11.0",
29
+ "@atlaskit/tokens": "^5.6.0",
30
+ "@babel/runtime": "^7.0.0",
31
+ "@compiled/react": "^0.18.3"
32
+ },
33
+ "peerDependencies": {
34
+ "react": "^18.2.0"
35
+ },
36
+ "devDependencies": {
37
+ "@af/integration-testing": "workspace:^",
38
+ "@af/visual-regression": "workspace:^",
39
+ "@atlaskit/editor-toolbar": "^0.0.5",
40
+ "@atlaskit/ssr": "workspace:^",
41
+ "@atlaskit/visual-regression": "workspace:^",
42
+ "@testing-library/react": "^13.4.0",
43
+ "react-dom": "^18.2.0",
44
+ "typescript": "~5.4.2"
45
+ },
46
+ "techstack": {
47
+ "@atlassian/frontend": {
48
+ "import-structure": [
49
+ "atlassian-conventions"
50
+ ],
51
+ "circular-dependencies": [
52
+ "file-and-folder-level"
53
+ ]
54
+ },
55
+ "@repo/internal": {
56
+ "dom-events": "use-bind-event-listener",
57
+ "analytics": [
58
+ "analytics-next"
59
+ ],
60
+ "design-tokens": [
61
+ "color"
62
+ ],
63
+ "theming": [
64
+ "react-context"
65
+ ],
66
+ "ui-components": [
67
+ "lite-mode"
68
+ ],
69
+ "deprecation": [
70
+ "no-deprecated-imports"
71
+ ],
72
+ "styling": [
73
+ "static",
74
+ "compiled"
75
+ ],
76
+ "imports": [
77
+ "import-no-extraneous-disable-for-examples-and-docs"
78
+ ]
79
+ }
80
+ },
81
+ "name": "@atlaskit/editor-toolbar-model",
82
+ "version": "0.0.1",
83
+ "description": "register and render toolbar component",
84
+ "author": "Atlassian Pty Ltd",
85
+ "license": "Apache-2.0",
86
+ "publishConfig": {
87
+ "registry": "https://registry.npmjs.org/"
88
+ }
89
+ }