diff --git a/.gitignore b/.gitignore
index 4c91ab0..76f1a8f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@
.env
app/node_modules
+remix/node_modules
+next/node_modules
app-next/node_modules
api/node_modules
node_modules
diff --git a/raycast/package.json b/raycast/package.json
index 48ff3c2..39aa9ea 100644
--- a/raycast/package.json
+++ b/raycast/package.json
@@ -93,7 +93,6 @@
"title": "Commander",
"description": "Open Thingtime Commander",
"mode": "view",
- "fallbackText": "test2",
"keywords": [
"commander",
"thingtime",
@@ -107,7 +106,38 @@
"key": "name",
"title": "Name of Command to run",
"description": "The name of the command/function to run",
- "defaultValue": "Menu"
+ "defaultValue": "MagicInput"
+ }
+ ]
+ },
+ {
+ "name": "commanderMagicInput",
+ "title": "Magic Input",
+ "description": "Evaluates a Magic Input",
+ "mode": "no-view",
+ "keywords": [
+ "commander",
+ "thingtime",
+ "ai"
+ ],
+ "arguments": [
+ {
+ "placeholder": "Path",
+ "name": "path",
+ "type": "text",
+ "description": "The path to open the new finder window at",
+ "required": false
+ }
+ ],
+ "preferences": [
+ {
+ "name": "name",
+ "required": false,
+ "type": "textfield",
+ "key": "name",
+ "title": "Name of Command to run",
+ "description": "The name of the command/function to run",
+ "defaultValue": "openNewFinderWindow"
}
]
},
@@ -116,7 +146,6 @@
"title": "Open New Finder Window",
"description": "Open new finder window",
"mode": "no-view",
- "fallbackText": "test2",
"keywords": [
"commander",
"thingtime",
@@ -148,7 +177,6 @@
"title": "Trim image",
"description": "Will trim all whitespace from an image",
"mode": "no-view",
- "fallbackText": "test2",
"keywords": [
"commander",
"thingtime",
@@ -171,7 +199,6 @@
"title": "mp4 to mp3",
"description": "Converts an mp4 into an mp3 using ffmpeg at 320Kbps",
"mode": "no-view",
- "fallbackText": "test2",
"keywords": [
"commander",
"thingtime",
diff --git a/remix/app/components/Branding/Branding.tsx b/remix/app/components/Branding/Branding.tsx
new file mode 100644
index 0000000..46795b0
--- /dev/null
+++ b/remix/app/components/Branding/Branding.tsx
@@ -0,0 +1,11 @@
+import { Box, Heading } from '@chakra-ui/react';
+import { Logo } from './Logo';
+
+export const Branding = () => {
+ return (
+
+ Branding
+
+
+ );
+};
diff --git a/remix/app/components/Branding/Logo.tsx b/remix/app/components/Branding/Logo.tsx
new file mode 100644
index 0000000..b6251fb
--- /dev/null
+++ b/remix/app/components/Branding/Logo.tsx
@@ -0,0 +1,87 @@
+import { Box, Center, Flex, Slider, SliderFilledTrack, SliderThumb, SliderTrack } from '@chakra-ui/react';
+import React, { useMemo, useState } from 'react';
+
+export const Logo = () => {
+ // a completely dynamic and interactive logo
+ // uses borders, border radius, and colour themes to create a simple timeless beautiful logo
+
+ // const defaultThemeRaw = ['white', '#F20009', '#FD5F00', '#FFEB03', '#52E013', '#09A7EC', '#982E77', 'white'];
+ const defaultThemeRaw = ['#F20009', '#FD5F00', '#FFEB03', '#52E013', '#09A7EC', '#982E77', 'white'];
+
+ const [reverseColours, setReverseColours] = useState(false);
+
+ const defaultTheme = reverseColours ? defaultThemeRaw?.reverse() : defaultThemeRaw;
+
+ const [theme, setTheme] = useState('blue');
+
+ const [squares, setSquares] = useState(9);
+
+ const [width, setWidth] = useState(250);
+
+ const [height, setHeight] = useState(250);
+
+ // logo is a T/plus shape made of two intersecting squares
+ // you can toggle border sides on both squares to create different shapes
+
+ const [borderWidth, setBorderWidth] = useState(18);
+
+ const [borderRadius, setBorderRadius] = useState(12);
+
+ const squaresArray = Array.from({ length: squares }, (_, index) => index);
+
+ const [spacing, setSpacing] = useState(borderWidth);
+
+ // log squaresArray
+ console.debug('tt.squaresArray', squaresArray);
+
+ // basically the 5 squares that make up a plus but with the centre one missing
+
+ const [divisions, setDivisions] = useState(3);
+
+ const [divisionHeight, setDivisionHeight] = useState(100 / divisions);
+
+ const [divisionWidth, setDivisionWidth] = useState(100 / divisions);
+
+ const uuid = useMemo(() => {
+ return Math.random().toString(36).substring(2) + Date.now().toString(36);
+ }, []);
+
+ return (
+ <>
+ {/* these are the controls */}
+ {/* border radius use chakra slider */}
+
+
+
+
+
+ 🟡
+
+
+
+ {squaresArray.map((_, idx) => {
+ // technically not even in programming terms cause it starts at 0 😂
+
+ const humanIdx = idx + 1;
+
+ const even = humanIdx % 2 === 0;
+
+ const colourIndex = Math.round(idx / 2);
+
+ // log the colourIndex
+ console.debug('tt.colourIndex', colourIndex);
+
+ return (
+
+ );
+ })}
+
+ >
+ );
+};
diff --git a/remix/app/components/Branding/LogoOld2.tsx b/remix/app/components/Branding/LogoOld2.tsx
new file mode 100644
index 0000000..4f7c3d2
--- /dev/null
+++ b/remix/app/components/Branding/LogoOld2.tsx
@@ -0,0 +1,129 @@
+import { Box, Center, Flex, Slider, SliderFilledTrack, SliderThumb, SliderTrack } from '@chakra-ui/react';
+import React, { useState } from 'react';
+
+export const LogoOld2 = () => {
+ // a completely dynamic and interactive logo
+ // uses borders, border radius, and colour themes to create a simple timeless beautiful logo
+
+ // const defaultThemeRaw = ['white', '#F20009', '#FD5F00', '#FFEB03', '#52E013', '#09A7EC', '#982E77', 'white'];
+ const defaultThemeRaw = ['#F20009', '#FD5F00', '#FFEB03', '#52E013', '#09A7EC', '#982E77', 'white'];
+
+ const [reverseColours, setReverseColours] = useState(false);
+
+ const defaultTheme = reverseColours ? defaultThemeRaw?.reverse() : defaultThemeRaw;
+
+ const [theme, setTheme] = useState('blue');
+
+ const [squares, setSquares] = useState(8);
+
+ const [width, setWidth] = useState(50);
+
+ const [height, setHeight] = useState(50);
+
+ // logo is a T/plus shape made of two intersecting squares
+ // you can toggle border sides on both squares to create different shapes
+
+ const [borderWidth, setBorderWidth] = useState(18);
+
+ const [borderRadius, setBorderRadius] = useState(12);
+
+ const squaresArray = Array.from({ length: squares }, (_, index) => index);
+
+ const [spacing, setSpacing] = useState(borderWidth);
+
+ // log squaresArray
+ console.debug('tt.squaresArray', squaresArray);
+
+ return (
+ <>
+ {/* these are the controls */}
+ {/* border radius use chakra slider */}
+
+
+
+
+
+ 🟡
+
+
+
+ {/* border top left squares */}
+ {squaresArray.map((_, index) => {
+ const top = index * spacing;
+ const left = index * spacing;
+ const colour = defaultTheme[index];
+
+ const square = (
+
+ {/* another box which acts as a mask */}
+
+ {/* */}
+
+ );
+
+ return square;
+ })}
+
+ {/* make squares for bottom right */}
+
+ {squaresArray.map((_, index) => {
+ const bottom = index * spacing + height * 2;
+ const right = index * spacing + width * 2;
+ const colour = defaultTheme[index];
+
+ const square = (
+
+ {/* another box which acts as a mask */}
+
+ {/* */}
+
+ );
+
+ return square;
+ })}
+
+ >
+ );
+};
diff --git a/remix/app/components/Editor/Editor.tsx b/remix/app/components/Editor/Editor.tsx
index a76b44d..d1c5316 100644
--- a/remix/app/components/Editor/Editor.tsx
+++ b/remix/app/components/Editor/Editor.tsx
@@ -8,8 +8,8 @@ export const Editor = (props) => {
return (
<>
- {/* only on client side render editor */}
+ {/* only on client side render editor */}
Loading...}>
diff --git a/remix/app/components/Nav/Nav.tsx b/remix/app/components/Nav/Nav.tsx
index 226fe54..32d2f51 100644
--- a/remix/app/components/Nav/Nav.tsx
+++ b/remix/app/components/Nav/Nav.tsx
@@ -136,11 +136,11 @@ export const Nav = (props) => {
)}
{/* TODO - Add conditional only show if loggedIn */}
-
+ {/*
-
+ */}
diff --git a/remix/app/components/Thingtime/SettingsMenu.tsx b/remix/app/components/Thingtime/SettingsMenu.tsx
index 6387c79..118fb64 100644
--- a/remix/app/components/Thingtime/SettingsMenu.tsx
+++ b/remix/app/components/Thingtime/SettingsMenu.tsx
@@ -1,146 +1,143 @@
-import React, { useState } from "react"
-import ClickAwayListener from "react-click-away-listener"
-import { Center, Flex, Text } from "@chakra-ui/react"
+import React, { useState } from 'react';
+import ClickAwayListener from 'react-click-away-listener';
+import { Center, Flex, Text } from '@chakra-ui/react';
-import { Icon } from "../Icon/Icon"
-import { useThingtime } from "./useThingtime"
+import { Icon } from '../Icon/Icon';
+import { useThingtime } from './useThingtime';
export const SettingsMenu = (props) => {
- const [show, setShow] = useState(false)
- const hideRef = React.useRef(null)
- const [opacity, setOpacity] = React.useState(props?.opacity === 0 ? 0 : 1)
- const [pinStatus, setPinStatus] = React.useState(false)
+ const [show, setShow] = useState(false);
+ const hideRef = React.useRef(null);
+ const [opacity, setOpacity] = React.useState(props?.opacity === 0 ? 0 : 1);
+ const [pinStatus, setPinStatus] = React.useState(false);
const stateRef = React.useRef({
- pinStatus,
- })
+ pinStatus
+ });
React.useEffect(() => {
- stateRef.current.pinStatus = pinStatus
- }, [pinStatus])
+ stateRef.current.pinStatus = pinStatus;
+ }, [pinStatus]);
- const { thingtime, events } = useThingtime()
+ const { thingtime, events } = useThingtime();
- const opacityRef = React.useRef(null)
+ const opacityRef = React.useRef(null);
- const waitTime = 1555
+ const waitTime = 1555;
- const [uuid, setUuid] = React.useState(null)
+ const [uuid, setUuid] = React.useState(null);
React.useEffect(() => {
- setUuid(Math.random().toString(36).substring(7))
- }, [])
+ setUuid(Math.random().toString(36).substring(7));
+ }, []);
React.useEffect(() => {
const subscription = events.subscribe((event) => {
- if (event?.type === "settings-menu-hide" && event?.uuid !== uuid) {
+ if (event?.type === 'settings-menu-hide' && event?.uuid !== uuid) {
if (!stateRef?.current?.pinStatus || event?.force) {
- setShow(false)
- setOpacity(0)
+ setShow(false);
+ setOpacity(0);
}
}
- })
+ });
return () => {
- subscription?.unsubscribe?.()
- }
- }, [events, uuid])
+ subscription?.unsubscribe?.();
+ };
+ }, [events, uuid]);
React.useEffect(() => {
- clearInterval(opacityRef?.current)
+ clearInterval(opacityRef?.current);
if (props?.opacity) {
- setOpacity(props?.opacity)
+ setOpacity(props?.opacity);
} else {
opacityRef.current = setInterval(() => {
if (!stateRef?.current?.pinStatus) {
- setOpacity(props?.opacity)
- setShow(false)
+ setOpacity(props?.opacity);
+ setShow(false);
}
- }, waitTime)
+ }, waitTime);
}
- }, [props?.opacity])
+ }, [props?.opacity]);
React.useEffect(() => {
if (show || props?.opacity) {
- clearInterval(hideRef?.current)
+ clearInterval(hideRef?.current);
events.next({
- type: "settings-menu-hide",
- uuid,
- })
+ type: 'settings-menu-hide',
+ uuid
+ });
} else if (!show) {
- setPinStatus(false)
+ setPinStatus(false);
}
- }, [show, props?.opacity, events, uuid])
+ }, [show, props?.opacity, events, uuid]);
const maybeHide = React.useCallback(() => {
- clearInterval(hideRef?.current)
+ clearInterval(hideRef?.current);
hideRef.current = setTimeout(() => {
if (!stateRef?.current?.pinStatus) {
- setShow(false)
- setOpacity(0)
+ setShow(false);
+ setOpacity(0);
}
- }, waitTime)
- }, [])
+ }, waitTime);
+ }, []);
const showMenu = React.useCallback(() => {
- clearInterval(hideRef?.current)
- setShow(true)
- }, [])
+ clearInterval(hideRef?.current);
+ setShow(true);
+ }, []);
const hideMenu = React.useCallback(() => {
- setShow(false)
- }, [])
+ setShow(false);
+ }, []);
const basePadding = React.useMemo(() => {
- return 4
- }, [])
+ return 4;
+ }, []);
const types = React.useMemo(() => {
- const baseTypes = thingtime?.settings?.types?.javascript || {}
- const baseTypeKeys = Object.keys(baseTypes)
+ const baseTypes = thingtime?.settings?.types?.javascript || {};
+ const baseTypeKeys = Object.keys(baseTypes);
- const customTypes = thingtime?.settings?.types?.custom || {}
- const customTypeKeysRaw = Object.keys(customTypes)
+ const customTypes = thingtime?.settings?.types?.custom || {};
+ const customTypeKeysRaw = Object.keys(customTypes);
const customTypeKeys = customTypeKeysRaw?.filter((key) => {
- return !baseTypeKeys?.includes?.(key)
- })
+ return !baseTypeKeys?.includes?.(key);
+ });
const types = [
...(baseTypeKeys?.map?.((key) => {
return {
...baseTypes?.[key],
- key,
- }
+ key
+ };
}) || []),
...(customTypeKeys?.map?.((key) => {
return {
...customTypes?.[key],
- key,
- }
- }) || []),
- ]
+ key
+ };
+ }) || [])
+ ];
- return types
- }, [
- thingtime?.settings?.types?.javascript,
- thingtime?.settings?.types?.custom,
- ])
+ return types;
+ }, [thingtime?.settings?.types?.javascript, thingtime?.settings?.types?.custom]);
const onType = React.useCallback(
(args) => {
- props?.onType?.(args)
+ props?.onType?.(args);
},
[props?.onType]
- )
+ );
const onDelete = React.useCallback(
(type) => {
- props?.onDelete?.()
+ props?.onDelete?.();
},
[props?.onDelete]
- )
+ );
- const childIconSize = 10
- const iconSize = props?.iconSize || 7
+ const childIconSize = 10;
+ const iconSize = props?.iconSize || 7;
return (
@@ -149,7 +146,7 @@ export const SettingsMenu = (props) => {
// width="100%"
paddingRight={36}
opacity={opacity}
- transition={props?.transition || "all 0.2s ease-in-out"}
+ transition={props?.transition || 'all 0.2s ease-in-out'}
onMouseEnter={showMenu}
onMouseLeave={maybeHide}
>
@@ -159,6 +156,8 @@ export const SettingsMenu = (props) => {
cursor="pointer"
// onClick={deleteValue}
transition="all 0.2s ease-in-out"
+ // add title for hover context
+ title={`Options`}
>
@@ -169,7 +168,7 @@ export const SettingsMenu = (props) => {
left={0}
flexDirection="column"
opacity={show ? 1 : 0}
- pointerEvents={show ? "all" : "none"}
+ pointerEvents={show ? 'all' : 'none'}
>
{
padding="5px"
cursor="pointer"
onClick={() => setPinStatus((prev) => !prev)}
+ title={`Pin Options`}
>
-
+ {show === true && }
+ {/* edit mode menu item */}
+
+
+
+ Toggle Edit Mode
+
+
+
+
+
{!props?.readonly && (
@@ -200,17 +224,13 @@ export const SettingsMenu = (props) => {
// paddingRight={basePadding}
paddingLeft={basePadding}
_hover={{
- background: "greys.light",
+ background: 'greys.light'
}}
cursor="pointer"
// paddingX={basePadding * 1}
paddingY={basePadding / 2}
>
-
+
Types
@@ -228,12 +248,12 @@ export const SettingsMenu = (props) => {
types.map((type, idx) => {
const ret = (
div": {
- background: "greys.light",
- },
+ '&>div': {
+ background: 'greys.light'
+ }
}}
cursor="pointer"
onClick={() => onType({ type })}
@@ -247,11 +267,7 @@ export const SettingsMenu = (props) => {
paddingLeft={basePadding * 2}
paddingY={basePadding / 2}
>
-
+
{type?.label || type?.key || type}
@@ -259,18 +275,18 @@ export const SettingsMenu = (props) => {
{
- e?.preventDefault?.()
- e?.stopPropagation?.()
+ e?.preventDefault?.();
+ e?.stopPropagation?.();
// cancel bubble
- e?.nativeEvent?.stopImmediatePropagation?.()
+ e?.nativeEvent?.stopImmediatePropagation?.();
onType({
type,
- wrap: true,
- })
+ wrap: true
+ });
}}
>
@@ -278,8 +294,8 @@ export const SettingsMenu = (props) => {
)}
- )
- return ret
+ );
+ return ret;
})}
{!props?.readonly && props?.onDelete && (
@@ -287,18 +303,14 @@ export const SettingsMenu = (props) => {
alignItems="center"
flexDirection="row"
_hover={{
- background: "greys.light",
+ background: 'greys.light'
}}
cursor="pointer"
onClick={onDelete}
paddingX={basePadding * 1}
paddingY={basePadding / 2}
>
-
+
Recycle
@@ -308,5 +320,5 @@ export const SettingsMenu = (props) => {
- )
-}
+ );
+};
diff --git a/remix/app/routes/branding.tsx b/remix/app/routes/branding.tsx
new file mode 100644
index 0000000..f18a63d
--- /dev/null
+++ b/remix/app/routes/branding.tsx
@@ -0,0 +1,15 @@
+import { Box } from '@chakra-ui/react';
+import { Branding } from '~/components/Branding/Branding';
+import { TopSpacing } from '~/components/Layout/TopSpacing';
+import { Raw } from '~/components/MongoDB/Raw';
+import { RawResults } from '~/components/MongoDB/RawResults';
+
+export default function branding() {
+ const template = (
+ <>
+
+ >
+ );
+
+ return template;
+}
diff --git a/vercel.json b/vercel.json
new file mode 100644
index 0000000..e69de29