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