duckylib 0.1.3 → 0.1.4

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 (30) hide show
  1. package/dist/components/containers/AgeConfirm.svelte +4 -2
  2. package/dist/components/containers/AgeConfirm.svelte.d.ts +1 -1
  3. package/dist/components/containers/Column.svelte +3 -2
  4. package/dist/components/containers/Column.svelte.d.ts +1 -1
  5. package/dist/components/containers/HorizontalRule.svelte +39 -0
  6. package/dist/components/containers/HorizontalRule.svelte.d.ts +13 -0
  7. package/dist/components/containers/Loading.svelte +62 -0
  8. package/dist/components/containers/Loading.svelte.d.ts +3 -0
  9. package/dist/components/containers/Row.svelte +1 -0
  10. package/dist/components/containers/cards/{LinkCard.svelte → ButtonCard.svelte} +18 -10
  11. package/dist/components/containers/cards/ButtonCard.svelte.d.ts +15 -0
  12. package/dist/components/containers/navigation/Header.svelte +40 -4
  13. package/dist/components/containers/navigation/Header.svelte.d.ts +11 -2
  14. package/dist/components/containers/navigation/SearchBar.svelte +539 -0
  15. package/dist/components/containers/navigation/SearchBar.svelte.d.ts +22 -0
  16. package/dist/components/text/Code.svelte +19 -0
  17. package/dist/components/text/Code.svelte.d.ts +11 -0
  18. package/dist/components/text/Markdown.svelte +62 -8
  19. package/dist/components/text/Markdown.svelte.d.ts +8 -3
  20. package/dist/components/text/Text.svelte +17 -4
  21. package/dist/components/text/Text.svelte.d.ts +3 -2
  22. package/dist/components/text/Typewriter.svelte +3 -3
  23. package/dist/index.d.ts +0 -28
  24. package/dist/index.js +32 -3
  25. package/dist/styles/fonts.css +1 -0
  26. package/dist/styles/theme.css +4 -0
  27. package/package.json +4 -3
  28. package/dist/components/containers/cards/LinkCard.svelte.d.ts +0 -14
  29. package/dist/components/index.d.ts +0 -1
  30. package/dist/components/index.js +0 -2
@@ -12,14 +12,16 @@
12
12
 
13
13
  interface AgeConfirmProps {
14
14
  age?: number;
15
- references?: ("substances" | "sexual")[];
15
+ references?: ("substances" | "sexual" | "death" | "sh")[];
16
16
  }
17
17
 
18
18
  let {age = 18, references = []}: AgeConfirmProps = $props();
19
19
 
20
20
  const referenceMap = {
21
21
  "substances": "Alcohol, Drugs, and Substance Abuse",
22
- "sexual": "Sexual Content"
22
+ "sexual": "Sexual Content",
23
+ "death": "Death or Dying",
24
+ "sh": "Suicide, self-harm, or suicidal ideation"
23
25
  }
24
26
 
25
27
  let ageVerified = $state(getAgeVerified());
@@ -1,6 +1,6 @@
1
1
  interface AgeConfirmProps {
2
2
  age?: number;
3
- references?: ("substances" | "sexual")[];
3
+ references?: ("substances" | "sexual" | "death" | "sh")[];
4
4
  }
5
5
  declare const AgeConfirm: import("svelte").Component<AgeConfirmProps, {}, "">;
6
6
  type AgeConfirm = ReturnType<typeof AgeConfirm>;
@@ -7,7 +7,7 @@
7
7
  justifyContent?: "center" | "flex-start" | "flex-end" | "space-between";
8
8
  alignItems?: "center" | "flex-start" | "flex-end" | "space-between";
9
9
  textAlign?: "center" | "left" | "right" | "justify";
10
- gapEm?: number;
10
+ gapEm?: number | "auto";
11
11
  textWrap?: boolean;
12
12
  flexWrap?: boolean;
13
13
 
@@ -37,13 +37,14 @@ flex-direction: column;
37
37
  flex-wrap: ${flexWrap ? "wrap" : "nowrap"};
38
38
  justify-content: ${justifyContent};
39
39
  align-items: ${alignItems};
40
- gap: ${gapEm}em;
40
+ gap: ${gapEm === "auto" ? "auto" : `${gapEm}em`};
41
41
  border-radius: ${borderRadiusPx}px;
42
42
  text-align: ${textAlign};
43
43
  margin-left: ${marginLeftPx === "auto" ? "auto" : `${marginLeftPx}px`};
44
44
  margin-right: ${marginRightPx === "auto" ? "auto" : `${marginRightPx}px`};
45
45
  margin-bottom: ${marginBottomPx === "auto" ? "auto" : `${marginBottomPx}px`};
46
46
  margin-top: ${marginTopPx === "auto" ? "auto" : `${marginTopPx}px`};
47
+ background-color: ${backgroundColor};
47
48
 
48
49
  `}">
49
50
  {@render children()}
@@ -4,7 +4,7 @@ interface ColumnProps {
4
4
  justifyContent?: "center" | "flex-start" | "flex-end" | "space-between";
5
5
  alignItems?: "center" | "flex-start" | "flex-end" | "space-between";
6
6
  textAlign?: "center" | "left" | "right" | "justify";
7
- gapEm?: number;
7
+ gapEm?: number | "auto";
8
8
  textWrap?: boolean;
9
9
  flexWrap?: boolean;
10
10
  backgroundColor?: string | "transparent";
@@ -0,0 +1,39 @@
1
+ <script lang="ts">
2
+
3
+ interface RowProps {
4
+ textAlign?: "center" | "left" | "right";
5
+
6
+ borderRadiusPx?: number;
7
+
8
+ widthPx?: number | "fill" | "fit";
9
+ widthPercent?: number;
10
+
11
+ marginRightPx?: number | "auto";
12
+ marginLeftPx?: number | "auto";
13
+ marginTopPx?: number | "auto";
14
+ marginBottomPx?: number | "auto";
15
+ }
16
+
17
+ const { textAlign = "center", borderRadiusPx = 0, widthPx = "fill", widthPercent = 0, marginBottomPx = 0, marginLeftPx = 0, marginRightPx = 0, marginTopPx = 0 }: RowProps = $props();
18
+ </script>
19
+
20
+ <hr style="{`
21
+ width: ${widthPercent !== 0 ? `${widthPercent}%` : widthPx === "fill" ? "100%" : widthPx === "fit" ? "auto" : `${widthPx}px`};
22
+ ${borderRadiusPx > 0 ? `border-radius: ${borderRadiusPx}px;` : ""}
23
+ text-align: ${textAlign};
24
+ margin-left: ${marginLeftPx === "auto" ? "auto" : `${marginLeftPx}px`};
25
+ margin-right: ${marginRightPx === "auto" ? "auto" : `${marginRightPx}px`};
26
+ margin-bottom: ${marginBottomPx === "auto" ? "auto" : `${marginBottomPx}px`};
27
+ margin-top: ${marginTopPx === "auto" ? "auto" : `${marginTopPx}px`};
28
+ `}" />
29
+
30
+ <style>
31
+ @import url("../../styles/globals.css");
32
+
33
+ hr {
34
+ background-color: var(--crust) !important;
35
+ height: 3px;
36
+ border: none;
37
+ border-radius: var(--border-md);
38
+ }
39
+ </style>
@@ -0,0 +1,13 @@
1
+ interface RowProps {
2
+ textAlign?: "center" | "left" | "right";
3
+ borderRadiusPx?: number;
4
+ widthPx?: number | "fill" | "fit";
5
+ widthPercent?: number;
6
+ marginRightPx?: number | "auto";
7
+ marginLeftPx?: number | "auto";
8
+ marginTopPx?: number | "auto";
9
+ marginBottomPx?: number | "auto";
10
+ }
11
+ declare const HorizontalRule: import("svelte").Component<RowProps, {}, "">;
12
+ type HorizontalRule = ReturnType<typeof HorizontalRule>;
13
+ export default HorizontalRule;
@@ -0,0 +1,62 @@
1
+ <script lang="ts">
2
+ import Heading from "../text/Heading.svelte";
3
+ import Column from "./Column.svelte";
4
+ import Text from "../text/Text.svelte"
5
+ import { onMount } from "svelte";
6
+ import Symbol from "../text/Symbol.svelte";
7
+
8
+
9
+ let loaded = $state(false);
10
+
11
+ onMount(() => {
12
+ window.onscroll = (e) => {
13
+ if(!loaded) {
14
+ e.preventDefault();
15
+ window.scrollTo({top: 0, behavior: "instant"})
16
+ }
17
+ }
18
+
19
+ setTimeout(() => {
20
+ loaded = true;
21
+
22
+ }, 7e2)
23
+ })
24
+
25
+ </script>
26
+
27
+ {#if !loaded}
28
+ <div>
29
+ <Column marginLeftPx="auto" marginRightPx="auto" textWrap={true}>
30
+ <Column heightPx="fit" textWrap={true} widthPercent={95}>
31
+ <Symbol name="hourglass" sizePx={64} />
32
+ <Heading size={2} weight="boldest">Loading...</Heading>
33
+
34
+ <Text weight="normal" classList={["italic"]}>Your content is loading. Thank you for your patience.</Text>
35
+
36
+ </Column>
37
+ </Column>
38
+ </div>
39
+ {/if}
40
+
41
+ <style>
42
+ @import url("../../styles/globals.css");
43
+
44
+ div {
45
+ position: absolute;
46
+ top: 0;
47
+ left: 0;
48
+
49
+ width: 100%;
50
+ height: 110%;
51
+
52
+
53
+ padding: 0.33em;
54
+ margin: 0;
55
+ box-sizing: border-box;
56
+
57
+ background-color: var(--base);
58
+ color: var(--text);
59
+
60
+ z-index: 2000;
61
+ }
62
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const Loading: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type Loading = ReturnType<typeof Loading>;
3
+ export default Loading;
@@ -44,6 +44,7 @@ margin-left: ${marginLeftPx === "auto" ? "auto" : `${marginLeftPx}px`};
44
44
  margin-right: ${marginRightPx === "auto" ? "auto" : `${marginRightPx}px`};
45
45
  margin-bottom: ${marginBottomPx === "auto" ? "auto" : `${marginBottomPx}px`};
46
46
  margin-top: ${marginTopPx === "auto" ? "auto" : `${marginTopPx}px`};
47
+ background-color: ${backgroundColor};
47
48
  `}">
48
49
  {@render children()}
49
50
  </div>
@@ -1,27 +1,27 @@
1
1
  <script lang="ts">
2
- import type { Snippet } from "svelte";
3
2
  import Column from "../Column.svelte";
4
3
  import Symbol from "../../text/Symbol.svelte";
5
4
  import Row from "../Row.svelte";
6
5
  import { browser } from "$app/environment";
7
- import { goto } from "$app/navigation";
6
+ import Text from "../../text/Text.svelte";
8
7
 
9
- interface LinkCardButton {
8
+ interface ButtonCardButton {
10
9
  text: string;
11
- href: string;
12
10
  type: "success" | "danger" | "primary" | "secondary";
11
+ href?: string;
12
+ onclick?: ((e: MouseEvent) => void) | null;
13
13
  }
14
14
 
15
- interface LinkCardProps {
15
+ interface ButtonCardProps {
16
16
  text: string;
17
17
  title?: string;
18
18
 
19
- buttons: LinkCardButton[];
19
+ buttons: ButtonCardButton[];
20
20
 
21
21
  symbol?: string | null;
22
22
  }
23
23
 
24
- let { text, symbol = null, title = "", buttons }: LinkCardProps = $props();
24
+ let { text, symbol = null, title = "", buttons }: ButtonCardProps = $props();
25
25
  </script>
26
26
 
27
27
  <div>
@@ -37,9 +37,13 @@
37
37
  <p class="font-semibold">{text}</p>
38
38
  <Row gapEm={0.33} justifyContent="flex-start">
39
39
  {#each buttons as button}
40
- <button class={button.type} onclick={() => {
41
- if(browser) goto(button.href)
42
- }}>{button.text}</button>
40
+ <button class={button.type} data-icon="{button.href && !button.onclick}" onclick={async (e) => {
41
+ if(button.onclick) {
42
+ await button.onclick(e)
43
+ } else {
44
+ if(browser && button.href) window.open(button.href, "_blank")
45
+ }
46
+ }}>{#if button.href && !button.onclick}<Row heightPx="fit" gapEm={0.66}><Text inheritColor={true} weight="bolder">{button.text}</Text><Symbol name="open_in_new" sizePx={18} inheritColor={true} /></Row>{:else}<Text inheritColor={true} weight="bolder">{button.text}</Text>{/if}</button>
43
47
  {/each}
44
48
  </Row>
45
49
  </Column>
@@ -112,6 +116,10 @@
112
116
  font-weight: 700;
113
117
  }
114
118
 
119
+ button[data-icon="true"] {
120
+ padding: 0.33em 0.66em;
121
+ }
122
+
115
123
  button:hover {
116
124
  transition: all 0.2s;
117
125
  transform: scale(1.02) translateY(1px);
@@ -0,0 +1,15 @@
1
+ interface ButtonCardButton {
2
+ text: string;
3
+ type: "success" | "danger" | "primary" | "secondary";
4
+ href?: string;
5
+ onclick?: ((e: MouseEvent) => void) | null;
6
+ }
7
+ interface ButtonCardProps {
8
+ text: string;
9
+ title?: string;
10
+ buttons: ButtonCardButton[];
11
+ symbol?: string | null;
12
+ }
13
+ declare const ButtonCard: import("svelte").Component<ButtonCardProps, {}, "">;
14
+ type ButtonCard = ReturnType<typeof ButtonCard>;
15
+ export default ButtonCard;
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from "svelte";
3
3
  import Row from "../Row.svelte";
4
- import { getTheme } from "../../../index.js";
4
+ import { getTheme, getUserData } from "../../../index.js";
5
5
  import ThemeButton from "../../buttons/ThemeButton.svelte";
6
6
  import { page } from "$app/state";
7
7
  import { MediaQuery } from "svelte/reactivity";
@@ -10,6 +10,7 @@
10
10
  import LoginButton from "../../buttons/LoginButton.svelte";
11
11
  import UserToast from "../../buttons/UserToast.svelte";
12
12
  import { PUBLIC_MOBILE_SIZE_PX, PUBLIC_TABLET_SIZE_PX } from "$env/static/public";
13
+ import SearchBar, { type QueryMapKeys, type SearchResult } from "./SearchBar.svelte";
13
14
 
14
15
  interface HeaderNavigation {
15
16
  label: string;
@@ -26,7 +27,16 @@
26
27
  withThemeButton?: boolean;
27
28
  withIcons?: boolean;
28
29
 
29
- user?: Auth.User | null;
30
+ withSearchBar?: boolean;
31
+ onsearch?: ((query: string) => Promise<void>) | null;
32
+ onresult?: ((result: SearchResult) => Promise<void>) | null;
33
+ searchOptions?: SearchResult[];
34
+ searchQueryUrl?: string;
35
+ searchQueryObjMap?: {[key in QueryMapKeys]: string | null};
36
+ searchQueryDataKey?: string;
37
+
38
+ defaultNav?: boolean;
39
+
30
40
  authFeatures?: boolean;
31
41
 
32
42
  nav?: HeaderNavigation[];
@@ -41,12 +51,22 @@
41
51
 
42
52
  let {
43
53
  children = null,
54
+
44
55
  withThemeButton = true,
45
56
  withIcons = true,
57
+ defaultNav = true,
58
+
59
+ withSearchBar = false,
60
+ onsearch = null,
61
+ onresult = null,
62
+ searchOptions = [],
63
+ searchQueryDataKey,
64
+ searchQueryObjMap,
65
+ searchQueryUrl,
66
+
46
67
  emoji = "🦆",
47
68
  label = "",
48
69
 
49
- user = null,
50
70
  authFeatures = false,
51
71
 
52
72
  nav = [],
@@ -56,7 +76,11 @@
56
76
  return nav;
57
77
  }
58
78
 
59
- nav = [
79
+ function getDefaultNav(): boolean {
80
+ return defaultNav;
81
+ }
82
+
83
+ if(getDefaultNav()) nav = [
60
84
  {
61
85
  label: "Home",
62
86
  pathname: "/",
@@ -65,6 +89,14 @@
65
89
  ...getNav(),
66
90
  ];
67
91
 
92
+ function authFeaturesEnabled(): boolean {
93
+ return authFeatures;
94
+ }
95
+
96
+ let user: Auth.User | null = $state(null);
97
+
98
+ if(authFeaturesEnabled()) user = getUserData();
99
+
68
100
  const mobileQuery = new MediaQuery(`max-width: ${PUBLIC_MOBILE_SIZE_PX}px`);
69
101
  const tabletQuery = new MediaQuery(`max-width: ${PUBLIC_TABLET_SIZE_PX}px`);
70
102
  </script>
@@ -83,6 +115,7 @@
83
115
  <Row widthPx="fit" gapEm={mobileQuery.current ? 1 : 1.33}>
84
116
  {#each nav as n}
85
117
  <a
118
+ target="{n.pathname.startsWith("/") ? "_self" : "_blank"}"
86
119
  href={n.pathname}
87
120
  class="font-semibold{page.url.pathname ===
88
121
  n.pathname
@@ -121,6 +154,9 @@
121
154
  </Row>
122
155
  {/if}
123
156
  <Row widthPx="fit">
157
+ {#if withSearchBar && onresult !== null}
158
+ <SearchBar {onsearch} {onresult} options={searchOptions} queryDataKey={searchQueryDataKey} queryObjMap={searchQueryObjMap} queryUrl={searchQueryUrl}/>
159
+ {/if}
124
160
  {#if authFeatures}
125
161
  <Row widthPx="fit">
126
162
 
@@ -1,5 +1,5 @@
1
1
  import type { Snippet } from "svelte";
2
- import type { Auth } from "../../../types.ts";
2
+ import { type QueryMapKeys, type SearchResult } from "./SearchBar.svelte";
3
3
  interface HeaderNavigation {
4
4
  label: string;
5
5
  pathname: string;
@@ -11,7 +11,16 @@ interface HeaderProps {
11
11
  label?: string;
12
12
  withThemeButton?: boolean;
13
13
  withIcons?: boolean;
14
- user?: Auth.User | null;
14
+ withSearchBar?: boolean;
15
+ onsearch?: ((query: string) => Promise<void>) | null;
16
+ onresult?: ((result: SearchResult) => Promise<void>) | null;
17
+ searchOptions?: SearchResult[];
18
+ searchQueryUrl?: string;
19
+ searchQueryObjMap?: {
20
+ [key in QueryMapKeys]: string | null;
21
+ };
22
+ searchQueryDataKey?: string;
23
+ defaultNav?: boolean;
15
24
  authFeatures?: boolean;
16
25
  nav?: HeaderNavigation[];
17
26
  }