diff --git a/.changeset/loud-schools-share.md b/.changeset/loud-schools-share.md
new file mode 100644
index 00000000..6166ca81
--- /dev/null
+++ b/.changeset/loud-schools-share.md
@@ -0,0 +1,5 @@
+---
+"@tokens-studio/graph-engine": minor
+---
+
+Add a sort array node
diff --git a/packages/documentation/pages/nodes/array-nodes/_meta.json b/packages/documentation/pages/nodes/array-nodes/_meta.json
index 6e12b623..6901b4d2 100644
--- a/packages/documentation/pages/nodes/array-nodes/_meta.json
+++ b/packages/documentation/pages/nodes/array-nodes/_meta.json
@@ -4,5 +4,6 @@
"index-array": "Index array",
"reverse-array": "Reverse array",
"slice-array": "Slice array",
+ "sort-array": "Sort array",
"join-array": "Join array"
}
\ No newline at end of file
diff --git a/packages/graph-editor/src/components/flow/DropPanel/PanelItems.tsx b/packages/graph-editor/src/components/flow/DropPanel/PanelItems.tsx
index 3a8f32a7..e0a91148 100644
--- a/packages/graph-editor/src/components/flow/DropPanel/PanelItems.tsx
+++ b/packages/graph-editor/src/components/flow/DropPanel/PanelItems.tsx
@@ -1,4 +1,5 @@
import {
+ ArrowDownIcon,
BlendingModeIcon,
ButtonIcon,
ColorWheelIcon,
@@ -259,6 +260,11 @@ export const items = {
icon: '[a,b]',
text: 'Slice Array',
},
+ {
+ type: NodeTypes.SORT,
+ icon: ,
+ text: 'Sort Array',
+ },
{
type: NodeTypes.JOIN,
icon: '[,]',
diff --git a/packages/graph-editor/src/components/flow/nodes/accessibility/ColorBlindNessNode.tsx b/packages/graph-editor/src/components/flow/nodes/accessibility/ColorBlindNessNode.tsx
index 4e8747bb..df13fd4e 100644
--- a/packages/graph-editor/src/components/flow/nodes/accessibility/ColorBlindNessNode.tsx
+++ b/packages/graph-editor/src/components/flow/nodes/accessibility/ColorBlindNessNode.tsx
@@ -1,11 +1,4 @@
-import {
- Button,
- Checkbox,
- DropdownMenu,
- Label,
- Stack,
- Text,
-} from '@tokens-studio/ui';
+import { Button, DropdownMenu, Label, Stack, Text } from '@tokens-studio/ui';
import {
ColorBlindnessTypes,
node,
@@ -17,7 +10,6 @@ import {
import { PreviewColor } from '../../preview/color.tsx';
import { WrapNode, useNode } from '../../wrapper/nodeV2.tsx';
import { sentenceCase } from 'sentence-case';
-import PreviewNumber from '../../preview/number.tsx';
import React, { useCallback } from 'react';
const keys = Object.values(ColorBlindnessTypes);
diff --git a/packages/graph-editor/src/components/flow/nodes/array/sort.tsx b/packages/graph-editor/src/components/flow/nodes/array/sort.tsx
new file mode 100644
index 00000000..e9dd8caf
--- /dev/null
+++ b/packages/graph-editor/src/components/flow/nodes/array/sort.tsx
@@ -0,0 +1,107 @@
+import { Handle, HandleContainer } from '../../handles.tsx';
+import { PreviewAny } from '../../preview/any.tsx';
+import { PreviewArray } from '../../preview/array.tsx';
+import {
+ Button,
+ DropdownMenu,
+ Stack,
+ Text,
+ TextInput,
+} from '@tokens-studio/ui';
+import { WrapNode, useNode } from '../../wrapper/nodeV2.tsx';
+import {
+ node,
+ OrderMap,
+} from '@tokens-studio/graph-engine/nodes/array/sort.js';
+import React, { useCallback } from 'react';
+import { LabelNoWrap } from '#/components/label.tsx';
+import { sentenceCase } from 'sentence-case';
+
+const keys: string[] = Object.values(OrderMap);
+
+const SortArrayNode = () => {
+ const { input, state, output, setState } = useNode();
+ const setValue = useCallback((ev) => {
+ const value = ev.target.value;
+ const key = ev.currentTarget.dataset.key;
+ setState((state) => ({
+ ...state,
+ [key]: value,
+ }));
+ }, []);
+
+ const setDropdownValue = useCallback((ev) => {
+ const value = ev.currentTarget.dataset.value;
+ const key = ev.currentTarget.dataset.key;
+ setState((state) => ({
+ ...state,
+ [key]: value,
+ }));
+ }, []);
+
+ return (
+
+
+
+ Array
+
+
+
+ Sort By
+
+ {input.sortBy !== undefined ? (
+
+ ) : (
+
+ )}
+
+
+ Order
+
+
+
+
+
+
+
+ {keys.map((key, i) => {
+ if (!key) {
+ return ;
+ }
+
+ return (
+
+ {sentenceCase(key || '')}
+
+ );
+ })}
+
+
+
+
+
+
+
+ Output
+
+
+
+
+ );
+};
+
+export default WrapNode(SortArrayNode, {
+ ...node,
+ title: 'Sort array',
+});
diff --git a/packages/graph-editor/src/components/flow/nodes/index.ts b/packages/graph-editor/src/components/flow/nodes/index.ts
index a341dd34..7784d191 100644
--- a/packages/graph-editor/src/components/flow/nodes/index.ts
+++ b/packages/graph-editor/src/components/flow/nodes/index.ts
@@ -34,6 +34,7 @@ import RegexNode from './string/regexNode.tsx';
import RemapNode from './sets/remapNode.tsx';
import ResolveAliasesNode from './sets/resolveAliases.tsx';
import ReverseArrayNode from './array/reverse.tsx';
+import SortArrayNode from './array/sort.tsx';
import ScaleNode from './color/scaleNode.tsx';
import SinNode from './math/sinNode.tsx';
import SliceNode from './array/slice.tsx';
@@ -112,6 +113,7 @@ export const { nodeTypes, stateInitializer } = processTypes([
SinNode,
CosNode,
ReverseArrayNode,
+ SortArrayNode,
TanNode,
jsonNode,
ClampNode,
diff --git a/packages/graph-editor/src/components/label.tsx b/packages/graph-editor/src/components/label.tsx
index 27bd67fe..d2e2035c 100644
--- a/packages/graph-editor/src/components/label.tsx
+++ b/packages/graph-editor/src/components/label.tsx
@@ -1,7 +1,9 @@
import { Label } from '@tokens-studio/ui';
import React from 'react';
-export const LabelNoWrap = ({ children, ...rest }: typeof Label) => {
+export interface ILabelNoWrap extends React.ComponentProps {}
+
+export const LabelNoWrap = ({ children, ...rest }: ILabelNoWrap) => {
return (