6 | @if (users$ | async; as users) {
7 | {{ users.length }}
8 | }
9 |
`
10 |
--------------------------------------------------------------------------------
/src/app/templates/banana.ts:
--------------------------------------------------------------------------------
1 | export const bananaBoxTemplate = `
`
--------------------------------------------------------------------------------
/src/app/templates/child-component.ts:
--------------------------------------------------------------------------------
1 | export const childComponentTemplate = `
`
2 |
--------------------------------------------------------------------------------
/src/app/templates/default.ts:
--------------------------------------------------------------------------------
1 | export const defaultTemplate =
2 | `
This is a static text node.
And this is a dynamic text node: {{test}}
3 | @if(isVisible) {
4 |
Some label
5 | }`
6 |
--------------------------------------------------------------------------------
/src/app/templates/event-bindings.ts:
--------------------------------------------------------------------------------
1 | export const eventBindingsTemplate = `
2 |
3 |
`
4 |
--------------------------------------------------------------------------------
/src/app/templates/for-loops.ts:
--------------------------------------------------------------------------------
1 | export const forLoopsTemplate =
2 | `
For loops examples
3 | @for(item of [1,2,3,4]; track $index) {
4 |
{{item}}
5 | }
6 |
7 |
8 |
9 |
{{item}}`
10 |
--------------------------------------------------------------------------------
/src/app/templates/if-else-reference.ts:
--------------------------------------------------------------------------------
1 | export const ifElseReferenceTemplate =
2 | `
3 | Welcome back, friend.
4 |
5 |
6 |
7 | Please friend, login.
8 | `
9 |
--------------------------------------------------------------------------------
/src/app/templates/if-then-else.ts:
--------------------------------------------------------------------------------
1 | export const ifThenElseTemplate =
2 | `@if (a > b) {
3 | {{a}} is greater than {{b}}
4 | } @else if (b > a) {
5 | {{a}} is less than {{b}}
6 | } @else {
7 | {{a}} is equal to {{b}}
8 | }`
9 |
--------------------------------------------------------------------------------
/src/app/templates/index.ts:
--------------------------------------------------------------------------------
1 | import { asyncPipeTemplate } from "./async-pipe";
2 | import { bananaBoxTemplate } from "./banana";
3 | import { childComponentTemplate } from "./child-component";
4 | import { defaultTemplate } from "./default";
5 | import { eventBindingsTemplate } from "./event-bindings";
6 | import { forLoopsTemplate } from "./for-loops";
7 | import { ifElseReferenceTemplate } from "./if-else-reference";
8 | import { ifThenElseTemplate } from "./if-then-else";
9 | import { nestedNodesTemplate } from "./nested-nodes";
10 | import { NgModelTemplate } from "./ng-model";
11 | import { simpleAtLet } from "./simple-at-let";
12 | import { templateLiteral } from "./template-literal";
13 |
14 | export type Template = Record<'label' | 'content', string>;
15 |
16 | export const templates: Template[] = [
17 | { label: 'default', content: defaultTemplate },
18 | { label: 'nested nodes', content: nestedNodesTemplate },
19 | { label: '@if/@else', content: ifThenElseTemplate },
20 | { label: '@for vs ngFor', content: forLoopsTemplate },
21 | { label: 'ngIf/else w/ template reference', content: ifElseReferenceTemplate },
22 | { label: 'event bindings', content: eventBindingsTemplate },
23 | { label: 'ng-model', content: NgModelTemplate },
24 | { label: 'async pipe', content: asyncPipeTemplate },
25 | { label: 'child component', content: childComponentTemplate },
26 | { label: 'simple @let', content: simpleAtLet},
27 | { label: 'double binding (banna in a box)', content: bananaBoxTemplate },
28 | { label: 'template literal', content: templateLiteral },
29 | ];
30 |
--------------------------------------------------------------------------------
/src/app/templates/nested-nodes.ts:
--------------------------------------------------------------------------------
1 | export const nestedNodesTemplate =
2 | `
3 |
4 |
5 |
6 |
7 |
8 |
9 |
`
10 |
--------------------------------------------------------------------------------
/src/app/templates/ng-model.ts:
--------------------------------------------------------------------------------
1 | export const NgModelTemplate =
2 | `
3 |
4 |
Value: {{ name }}
5 |
Valid: {{ ctrl.valid }}
6 |
7 |
`
8 |
--------------------------------------------------------------------------------
/src/app/templates/simple-at-let.ts:
--------------------------------------------------------------------------------
1 | export const simpleAtLet =
2 | `
3 | @let myVar = 5;
4 | {{myVar}}
5 |
`
6 |
--------------------------------------------------------------------------------
/src/app/templates/template-literal.ts:
--------------------------------------------------------------------------------
1 | export const templateLiteral =
2 | `
{{\`-- \${foo} --\`}}
`
3 |
--------------------------------------------------------------------------------
/src/app/zip.ts:
--------------------------------------------------------------------------------
1 | // Apply LZW-compression to a string and return base64 compressed string.
2 | export function zip(s: string): string {
3 | try {
4 | var dict: Record
= {};
5 | var data = (s + '').split('');
6 | var out: any[] = [];
7 | var currChar;
8 | var phrase = data[0];
9 | var code = 256;
10 | for (var i = 1; i < data.length; i++) {
11 | currChar = data[i];
12 | if (dict[phrase + currChar] != null) {
13 | phrase += currChar;
14 | } else {
15 | out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
16 | dict[phrase + currChar] = code;
17 | code++;
18 | phrase = currChar;
19 | }
20 | }
21 | out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
22 | for (var j = 0; j < out.length; j++) {
23 | out[j] = String.fromCharCode(out[j]);
24 | }
25 | return utoa(out.join(''));
26 | } catch (e) {
27 | console.log('Failed to zip string return empty string', e);
28 | return '';
29 | }
30 | }
31 |
32 | // Decompress an LZW-encoded base64 string
33 | export function unzip(base64ZippedString: string) {
34 | try {
35 | var s = atou(base64ZippedString);
36 | var dict: Record = {};
37 | var data = (s + '').split('');
38 | var currChar = data[0];
39 | var oldPhrase = currChar;
40 | var out = [currChar];
41 | var code = 256;
42 | var phrase;
43 | for (var i = 1; i < data.length; i++) {
44 | var currCode = data[i].charCodeAt(0);
45 | if (currCode < 256) {
46 | phrase = data[i];
47 | } else {
48 | phrase = dict[currCode] ? dict[currCode] : oldPhrase + currChar;
49 | }
50 | out.push(phrase);
51 | currChar = phrase.charAt(0);
52 | dict[code] = oldPhrase + currChar;
53 | code++;
54 | oldPhrase = phrase;
55 | }
56 | return out.join('');
57 | } catch (e) {
58 | console.log('Failed to unzip string return empty string', e);
59 | return '';
60 | }
61 | }
62 |
63 | // ucs-2 string to base64 encoded ascii
64 | function utoa(str: string): string {
65 | return window.btoa(unescape(encodeURIComponent(str)));
66 | }
67 | // base64 encoded ascii to ucs-2 string
68 | function atou(str: string): string {
69 | return decodeURIComponent(escape(window.atob(str)));
70 | }
71 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AngularCompilerOutput
6 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { bootstrapApplication } from '@angular/platform-browser';
2 | import { appConfig } from './app/app.config';
3 | import { AppComponent } from './app/app.component';
4 |
5 | bootstrapApplication(AppComponent, appConfig)
6 | .catch((err) => console.error(err));
7 |
--------------------------------------------------------------------------------
/src/styles.scss:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 | /* Add application styles & imports to this file! */
3 |
4 | // Following styles have been mostly borrowed from the angular.dev style
5 | @use "styles/button";
6 | @use "styles/colors";
7 | @import "@angular/cdk/overlay-prebuilt.css";
8 |
9 | @include button.button();
10 |
11 | html,
12 | body {
13 | height: 100%;
14 | }
15 | body {
16 | margin: 0;
17 | font-family: Roboto, "Helvetica Neue", sans-serif;
18 | }
19 |
20 | header {
21 | text-align: center;
22 | font-size: 16pt;
23 | font-weight: bold;
24 | padding: 8px;
25 | margin-bottom: 8px;
26 | color: white;
27 | background: var(--red-to-pink-to-purple-horizontal-gradient);
28 | }
29 |
30 | body {
31 | font-family: sans-serif;
32 | }
33 |
34 | main {
35 | padding: 18px 18px 32px;
36 | }
37 |
38 | h2 {
39 | margin-top: 0;
40 | }
41 |
42 | section {
43 | display: flex;
44 | gap: 12px;
45 | }
46 |
47 | hr {
48 | border-radius: 8px;
49 | height: 8px;
50 | background: var(--red-to-pink-to-purple-horizontal-gradient);
51 | border: none;
52 | }
53 |
54 | .error {
55 | color: var(--hot-red);
56 | }
57 |
58 | textarea {
59 | flex: 1;
60 | }
61 |
62 | pre {
63 | padding: 12px;
64 | border-radius: 8px;
65 | }
66 |
67 | .shiki {
68 | code {
69 | counter-reset: step;
70 | counter-increment: step 0;
71 | }
72 |
73 | code .line::before {
74 | content: counter(step);
75 | counter-increment: step;
76 | width: 1rem;
77 | margin-right: 1.5rem;
78 | display: inline-block;
79 | text-align: right;
80 | color: rgba(115, 138, 148, 0.4);
81 | }
82 | }
83 |
84 | .controls {
85 | display: flex;
86 | flex-direction: column;
87 | align-items: end;
88 | justify-content: space-between;
89 | gap: 8px;
90 |
91 | option {
92 | padding: 8px;
93 | }
94 | }
95 |
96 | .twitter {
97 | background: var(--red-to-pink-to-purple-horizontal-gradient);
98 | background-clip: text;
99 | -webkit-text-fill-color: transparent;
100 | text-decoration: underline;
101 |
102 | a {
103 | font-weight: bold;
104 | }
105 | }
106 |
107 | .adev-template-select {
108 | margin-block-end: 0.5rem;
109 |
110 | label {
111 | color: var(--quaternary-contrast);
112 | font-size: 0.875rem;
113 | margin-block-end: 0.3rem;
114 | margin-inline-start: 0.45rem;
115 | display: block;
116 | }
117 |
118 | // cdk select button
119 | button {
120 | font-size: 0.875rem;
121 | border: 1px solid var(--senary-contrast);
122 | border-radius: 0.25rem;
123 | width: 200px;
124 | display: flex;
125 | justify-content: space-between;
126 | align-items: center;
127 | padding-block: 0.5rem;
128 | font-weight: 400;
129 | transition: border 0.3s ease;
130 | span {
131 | color: var(--primary-contrast);
132 | transition: color 0.3s ease;
133 | margin-inline-start: 0.1rem;
134 | }
135 |
136 | docs-icon {
137 | font-size: 1.3rem;
138 | color: var(--quaternary-contrast);
139 | transition: color 0.3s ease;
140 | }
141 | }
142 | }
143 |
144 | // select dropdown
145 | .adev-template-dropdown {
146 | border: 1px solid var(--senary-contrast);
147 | border-radius: 0.25rem;
148 | padding: 0;
149 | transform: translateY(-0.7rem);
150 |
151 | li {
152 | list-style: none;
153 | width: 198px;
154 | box-sizing: border-box;
155 |
156 | button {
157 | background: var(--page-background);
158 | font-size: 0.875rem;
159 | width: 100%;
160 | text-align: left;
161 | padding-block: 0.5rem;
162 | color: var(--quaternary-contrast);
163 | transition:
164 | color 0.3s ease,
165 | background 0.3s ease;
166 | font-weight: 400;
167 |
168 | &:hover {
169 | background: var(--senary-contrast);
170 | color: var(--primary-contrast);
171 | }
172 | }
173 | }
174 | }
175 |
176 | .mat-typography {
177 | font:
178 | 400 1rem / 1.5rem Roboto,
179 | sans-serif;
180 | letter-spacing: 0.031rem;
181 | }
182 |
--------------------------------------------------------------------------------
/src/styles/_button.scss:
--------------------------------------------------------------------------------
1 | @mixin button() {
2 | button {
3 | font-family: var(--inter-font);
4 | background: transparent;
5 | -webkit-appearance: none;
6 | border: 0;
7 | font-weight: 600;
8 |
9 | // Remove excess padding and border in Firefox 4+
10 | &::-moz-focus-inner {
11 | border: 0;
12 | padding: 0;
13 | }
14 |
15 | &:disabled {
16 | cursor: not-allowed;
17 | }
18 | }
19 |
20 | @property --angle {
21 | syntax: "";
22 | initial-value: 90deg;
23 | inherits: false;
24 | }
25 |
26 | @keyframes spin-gradient {
27 | 0% {
28 | --angle: 90deg;
29 | }
30 | 100% {
31 | --angle: 450deg;
32 | }
33 | }
34 |
35 | .docs-primary-btn {
36 | cursor: pointer;
37 | border: none;
38 | outline: none;
39 | position: relative;
40 | border-radius: 0.25rem;
41 | padding: 0.75rem 1.5rem;
42 | width: max-content;
43 | color: transparent;
44 |
45 | // border gradient / background
46 | --angle: 90deg;
47 | background: linear-gradient(
48 | var(--angle),
49 | var(--orange-red) 0%,
50 | var(--vivid-pink) 50%,
51 | var(--electric-violet) 100%
52 | );
53 |
54 | docs-icon {
55 | z-index: var(--z-index-content);
56 | position: relative;
57 | }
58 |
59 | // text & radial gradient
60 | &::before {
61 | content: attr(text);
62 | position: absolute;
63 | inset: 1px;
64 | background: var(--page-bg-radial-gradient);
65 | border-radius: 0.2rem;
66 | display: flex;
67 | align-items: center;
68 | justify-content: center;
69 | transition:
70 | opacity 0.3s ease,
71 | background 0.3s ease;
72 | color: var(--primary-contrast);
73 | }
74 |
75 | // solid color negative space - CSS transition supported
76 | &::after {
77 | content: attr(text);
78 | position: absolute;
79 | inset: 1px;
80 | background: var(--page-background);
81 | border-radius: 0.2rem;
82 | display: flex;
83 | align-items: center;
84 | justify-content: center;
85 | transition:
86 | opacity 0.3s ease,
87 | background 0.3s ease;
88 | color: var(--primary-contrast);
89 | }
90 |
91 | &:hover {
92 | animation: spin-gradient 4s linear infinite forwards;
93 | &::before {
94 | background-color: var(--page-background);
95 | background: var(--soft-pink-radial-gradient);
96 | opacity: 0.9;
97 | }
98 | &::after {
99 | opacity: 0;
100 | }
101 | }
102 |
103 | &:active {
104 | &::before {
105 | opacity: 0.8;
106 | }
107 | }
108 |
109 | &:disabled {
110 | //gradient stroke
111 | background: var(--quinary-contrast);
112 | color: var(--quinary-contrast);
113 |
114 | &::before {
115 | background-color: var(--page-background);
116 | background: var(--page-bg-radial-gradient);
117 | opacity: 1;
118 | }
119 |
120 | docs-icon {
121 | color: var(--quinary-contrast);
122 | }
123 | }
124 |
125 | docs-icon {
126 | z-index: var(--z-index-icon);
127 | color: var(--primary-contrast);
128 | }
129 | }
130 |
131 | .docs-secondary-btn {
132 | border: 1px solid var(--senary-contrast);
133 | background: var(--page-background);
134 | padding: 0.75rem 1.5rem;
135 | border-radius: 0.25rem;
136 | color: var(--primary-contrast);
137 | transition: background 0.3s ease;
138 |
139 | docs-icon {
140 | color: var(--quaternary-contrast);
141 | transition: color 0.3s ease;
142 | }
143 |
144 | &:hover {
145 | background: var(--septenary-contrast);
146 |
147 | docs-icon {
148 | color: var(--primary-contrast);
149 | }
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/src/styles/_colors.scss:
--------------------------------------------------------------------------------
1 | // Colors
2 | // Using OKLCH color space for better color reproduction on P3 displays,
3 | // as well as better human-readability
4 | // --> https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch
5 |
6 | @mixin root-definitions() {
7 | // PRIMITIVES
8 | // Colors
9 | --bright-blue: oklch(51.01% 0.274 263.83); // #0546ff
10 | --indigo-blue: oklch(51.64% 0.229 281.65); // #5c44e4
11 | --electric-violet: oklch(53.18% 0.28 296.97); // #8514f5
12 | --french-violet: oklch(47.66% 0.246 305.88); // #8001c6
13 | --vivid-pink: oklch(69.02% 0.277 332.77); // #f637e3
14 | --hot-pink: oklch(59.91% 0.239 8.14); // #e90464
15 | --hot-red: oklch(61.42% 0.238 15.34); // #f11653
16 | --orange-red: oklch(63.32% 0.24 31.68); // #fa2c04
17 | --super-green: oklch(
18 | 79.12% 0.257 155.13
19 | ); // #00c572 // Used for success, merge additions, etc.
20 |
21 | // subtle-purple is used for inline-code bg, docs-card hover bg & docs-code header bg
22 | --subtle-purple: color-mix(in srgb, var(--bright-blue) 5%, white 10%);
23 | --light-blue: color-mix(in srgb, var(--bright-blue), white 50%);
24 | --light-violet: color-mix(in srgb, var(--electric-violet), white 65%);
25 | --light-orange: color-mix(in srgb, var(--orange-red), white 50%);
26 | --light-pink: color-mix(in srgb, var(--vivid-pink) 10%, white 80%);
27 |
28 | // SYMBOLIC COLORS
29 | // Used for Type Labels
30 | --symbolic-purple: oklch(42.86% 0.29 266.4); //#1801ea
31 | --symbolic-gray: oklch(66.98% 0 0); // #959595
32 | --symbolic-blue: oklch(42.45% 0.223 263.38); // #0037c5;
33 | --symbolic-pink: oklch(63.67% 0.254 13.47); // #ff025c
34 | --symbolic-orange: oklch(
35 | 64.73% 0.23769984683784018 33.18328352127882
36 | ); // #fe3700
37 | --symbolic-yellow: oklch(78.09% 0.163 65.69); // #fd9f28
38 | --symbolic-green: oklch(67.83% 0.229 142.73); // #00b80a
39 | --symbolic-cyan: oklch(
40 | 67.05% 0.1205924489987394 181.34025902203868
41 | ); // #00ad9a
42 | --symbolic-magenta: oklch(
43 | 51.74% 0.25453048882711515 315.26261625862725
44 | ); // #9c00c8
45 | --symbolic-teal: oklch(57.59% 0.083 230.58); // #3f82a1
46 | --symbolic-brown: oklch(49.06% 0.128 46.41); // #994411
47 | --symbolic-lime: oklch(
48 | 70.33% 0.2078857836035299 135.66843631046476
49 | ); // #5dba00
50 |
51 | // Grays
52 | --gray-1000: oklch(16.93% 0.004 285.95); // #0f0f11
53 | --gray-900: oklch(19.37% 0.006 300.98); // #151417
54 | --gray-800: oklch(25.16% 0.008 308.11); // #232125
55 | --gray-700: oklch(36.98% 0.014 302.71); // #413e46
56 | --gray-600: oklch(44% 0.019 306.08); // #55505b
57 | --gray-500: oklch(54.84% 0.023 304.99); // #746e7c
58 | --gray-400: oklch(70.9% 0.015 304.04); // #a39fa9
59 | --gray-300: oklch(84.01% 0.009 308.34); // #ccc9cf
60 | --gray-200: oklch(91.75% 0.004 301.42); // #e4e3e6
61 | --gray-100: oklch(97.12% 0.002 325.59); // #f6f5f6
62 | --gray-50: oklch(98.81% 0 0); // #fbfbfb
63 |
64 | // GRADIENTS
65 | --red-to-pink-horizontal-gradient: linear-gradient(
66 | 90deg,
67 | var(--hot-pink) 11.42%,
68 | var(--hot-red) 34.83%,
69 | var(--vivid-pink) 60.69%
70 | );
71 |
72 | --red-to-pink-to-purple-horizontal-gradient: linear-gradient(
73 | 90deg,
74 | var(--orange-red) 0%,
75 | var(--vivid-pink) 50%,
76 | var(--electric-violet) 100%
77 | );
78 |
79 | --pink-to-highlight-to-purple-to-blue-horizontal-gradient: linear-gradient(
80 | 140deg,
81 | var(--vivid-pink) 0%,
82 | var(--vivid-pink) 15%,
83 | color-mix(in srgb, var(--vivid-pink), var(--electric-violet) 50%) 25%,
84 | color-mix(in srgb, var(--vivid-pink), var(--electric-violet) 10%) 35%,
85 | color-mix(in srgb, var(--vivid-pink), var(--orange-red) 50%) 42%,
86 | color-mix(in srgb, var(--vivid-pink), var(--orange-red) 50%) 44%,
87 | color-mix(in srgb, var(--vivid-pink), var(--page-background) 70%) 47%,
88 | var(--electric-violet) 48%,
89 | var(--bright-blue) 60%
90 | );
91 |
92 | --purple-to-blue-horizontal-gradient: linear-gradient(
93 | 90deg,
94 | var(--electric-violet) 0%,
95 | var(--bright-blue) 100%
96 | );
97 | --purple-to-blue-vertical-gradient: linear-gradient(
98 | 0deg,
99 | var(--electric-violet) 0%,
100 | var(--bright-blue) 100%
101 | );
102 |
103 | --red-to-orange-horizontal-gradient: linear-gradient(
104 | 90deg,
105 | var(--hot-pink) 0%,
106 | var(--orange-red) 100%
107 | );
108 | --red-to-orange-vertical-gradient: linear-gradient(
109 | 0deg,
110 | var(--hot-pink) 0%,
111 | var(--orange-red) 100%
112 | );
113 |
114 | --pink-to-purple-horizontal-gradient: linear-gradient(
115 | 90deg,
116 | var(--vivid-pink) 0%,
117 | var(--electric-violet) 100%
118 | );
119 | --pink-to-purple-vertical-gradient: linear-gradient(
120 | 0deg,
121 | var(--electric-violet) 0%,
122 | var(--vivid-pink) 100%
123 | );
124 |
125 | --purple-to-light-purple-vertical-gradient: linear-gradient(
126 | 0deg,
127 | var(--french-violet) 0%,
128 | var(--light-violet) 100%
129 | );
130 |
131 | --green-to-cyan-vertical-gradient: linear-gradient(
132 | 0deg,
133 | var(--symbolic-cyan) 0%,
134 | var(--super-green) 100%
135 | );
136 |
137 | --blue-to-teal-vertical-gradient: linear-gradient(
138 | 0deg,
139 | var(--bright-blue) 0%,
140 | var(--light-blue) 100%
141 | );
142 |
143 | --blue-to-cyan-vertical-gradient: linear-gradient(
144 | 0deg,
145 | var(--bright-blue) 0%,
146 | var(--symbolic-cyan) 100%
147 | );
148 |
149 | --black-to-gray-vertical-gradient: linear-gradient(
150 | 0deg,
151 | var(--primary-contrast) 0%,
152 | var(--gray-400) 100%
153 | );
154 |
155 | --red-to-pink-vertical-gradient: linear-gradient(
156 | 0deg,
157 | var(--hot-red) 0%,
158 | var(--vivid-pink) 100%
159 | );
160 | --orange-to-pink-vertical-gradient: linear-gradient(
161 | 0deg,
162 | var(--vivid-pink) 0%,
163 | var(--light-orange) 100%
164 | );
165 |
166 | // Radial Gradients
167 | --page-bg-radial-gradient: radial-gradient(circle, white 0%, white 100%);
168 | --soft-pink-radial-gradient: radial-gradient(
169 | circle at center bottom,
170 | var(--light-pink) 0%,
171 | white 80%
172 | );
173 |
174 | // ABSTRACTIONS light - dark
175 | // --full-contrast: black - white
176 | // --primary-constrast: gray-900 - gray-100
177 | // --secondary-contrast: gray-800 - gray-300
178 | // --tertiary-contrast: gray-700 - gray-300
179 | // --quaternary-contrast: gray-500 - gray-400
180 | // --quinary-contrast: gray-300 - gray-500
181 | // --senary-contrast: gray-200 - gray-700
182 | // --septenary-contrast: gray-100 - gray-800
183 | // --octonary-contrast: gray-50 - gray-900
184 | // --page-background white - gray-1000
185 |
186 | // LIGHT MODE is default
187 | // contrast - light mode
188 | --full-contrast: black;
189 | --primary-contrast: var(--gray-900);
190 | --secondary-contrast: var(--gray-800);
191 | --tertiary-contrast: var(--gray-700);
192 | --quaternary-contrast: var(--gray-500);
193 | --quinary-contrast: var(--gray-300);
194 | --senary-contrast: var(--gray-200);
195 | --septenary-contrast: var(--gray-100);
196 | --octonary-contrast: var(--gray-50);
197 | --page-background: white;
198 |
199 | // Home page
200 | // for the "unfilled" portion of the word that hasn't
201 | // been highlighted by the gradient
202 | --gray-unfilled: var(--gray-400);
203 | // TODO: convert oklch to hex at build time
204 | --webgl-page-background: #ffffff;
205 | --webgl-gray-unfilled: #a39fa9;
206 | }
207 |
208 | @mixin dark-mode-definitions() {
209 | // Contrasts
210 | --full-contrast: white;
211 | --primary-contrast: var(--gray-50);
212 | --secondary-contrast: var(--gray-300);
213 | --tertiary-contrast: var(--gray-300);
214 | --quaternary-contrast: var(--gray-400);
215 | --quinary-contrast: var(--gray-500);
216 | --senary-contrast: var(--gray-700);
217 | --septenary-contrast: var(--gray-800);
218 | --octonary-contrast: var(--gray-900);
219 | --page-background: var(--gray-1000);
220 |
221 | --bright-blue: color-mix(
222 | in srgb,
223 | oklch(51.01% 0.274 263.83),
224 | var(--full-contrast) 60%
225 | );
226 | --indigo-blue: color-mix(
227 | in srgb,
228 | oklch(51.64% 0.229 281.65),
229 | var(--full-contrast) 70%
230 | );
231 | --electric-violet: color-mix(
232 | in srgb,
233 | oklch(53.18% 0.28 296.97),
234 | var(--full-contrast) 70%
235 | );
236 | --french-violet: color-mix(
237 | in srgb,
238 | oklch(47.66% 0.246 305.88),
239 | var(--full-contrast) 70%
240 | );
241 | --vivid-pink: color-mix(
242 | in srgb,
243 | oklch(69.02% 0.277 332.77),
244 | var(--full-contrast) 70%
245 | );
246 | --hot-pink: color-mix(
247 | in srgb,
248 | oklch(59.91% 0.239 8.14),
249 | var(--full-contrast) 70%
250 | );
251 | --hot-red: color-mix(
252 | in srgb,
253 | oklch(61.42% 0.238 15.34),
254 | var(--full-contrast) 70%
255 | );
256 | --orange-red: color-mix(
257 | in srgb,
258 | oklch(63.32% 0.24 31.68),
259 | var(--full-contrast) 60%
260 | );
261 | --super-green: color-mix(
262 | in srgb,
263 | oklch(79.12% 0.257 155.13),
264 | var(--full-contrast) 70%
265 | );
266 |
267 | --light-pink: color-mix(
268 | in srgb,
269 | var(--vivid-pink) 5%,
270 | var(--page-background) 75%
271 | );
272 |
273 | --symbolic-purple: color-mix(
274 | in srgb,
275 | oklch(42.86% 0.29 266.4),
276 | var(--full-contrast) 65%
277 | );
278 | --symbolic-gray: color-mix(
279 | in srgb,
280 | oklch(66.98% 0 0),
281 | var(--full-contrast) 65%
282 | );
283 | --symbolic-blue: color-mix(
284 | in srgb,
285 | oklch(42.45% 0.223 263.38),
286 | var(--full-contrast) 65%
287 | );
288 | --symbolic-pink: color-mix(
289 | in srgb,
290 | oklch(63.67% 0.254 13.47),
291 | var(--full-contrast) 65%
292 | );
293 | --symbolic-orange: color-mix(
294 | in srgb,
295 | oklch(64.73% 0.23769984683784018 33.18328352127882),
296 | var(--full-contrast) 65%
297 | );
298 | --symbolic-yellow: color-mix(
299 | in srgb,
300 | oklch(78.09% 0.163 65.69),
301 | var(--full-contrast) 65%
302 | );
303 | --symbolic-green: color-mix(
304 | in srgb,
305 | oklch(67.83% 0.229 142.73),
306 | var(--full-contrast) 65%
307 | );
308 | --symbolic-cyan: color-mix(
309 | in srgb,
310 | oklch(67.05% 0.1205924489987394 181.34025902203868),
311 | var(--full-contrast) 65%
312 | );
313 | --symbolic-magenta: color-mix(
314 | in srgb,
315 | oklch(51.74% 0.25453048882711515 315.26261625862725),
316 | var(--full-contrast) 65%
317 | );
318 | --symbolic-teal: color-mix(
319 | in srgb,
320 | oklch(57.59% 0.083 230.58),
321 | var(--full-contrast) 65%
322 | );
323 | --symbolic-brown: color-mix(
324 | in srgb,
325 | oklch(49.06% 0.128 46.41),
326 | var(--full-contrast) 65%
327 | );
328 | --symbolic-lime: color-mix(
329 | in srgb,
330 | oklch(70.33% 0.2078857836035299 135.66843631046476),
331 | var(--full-contrast) 65%
332 | );
333 |
334 | --page-bg-radial-gradient: radial-gradient(circle, black 0%, black 100%);
335 | --soft-pink-radial-gradient: radial-gradient(
336 | circle at center bottom,
337 | var(--light-pink) 0%,
338 | color-mix(in srgb, black, transparent 15%) 80%
339 | );
340 |
341 | // Home page - dark mode
342 | --gray-unfilled: var(--gray-700);
343 | // TODO: convert oklch to hex at build time
344 | --webgl-page-background: #0f0f11;
345 | --webgl-gray-unfilled: #413e46;
346 |
347 | .docs-toggle {
348 | input {
349 | &:checked + .docs-slider {
350 | background: var(--pink-to-purple-horizontal-gradient) !important;
351 | }
352 | }
353 | }
354 | }
355 |
356 | @mixin mdc-definitions() {
357 | --mdc-snackbar-container-shape: 0.25rem;
358 | --mdc-snackbar-container-color: var(--page-background);
359 | --mdc-snackbar-supporting-text-color: var(--primary-contrast);
360 | }
361 |
362 | // LIGHT MODE (Explicit)
363 | .docs-light-mode {
364 | background-color: #ffffff;
365 | @include root-definitions();
366 | @include mdc-definitions();
367 | .docs-invert-mode {
368 | @include dark-mode-definitions();
369 | @include mdc-definitions();
370 | }
371 | }
372 |
373 | // DARK MODE (Explicit)
374 | .docs-dark-mode {
375 | background-color: oklch(16.93% 0.004 285.95);
376 | @include root-definitions();
377 | @include dark-mode-definitions();
378 | @include mdc-definitions();
379 | .docs-invert-mode {
380 | @include root-definitions();
381 | @include mdc-definitions();
382 | }
383 | }
384 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts"
10 | ],
11 | "include": [
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "outDir": "./dist/out-tsc",
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": true,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true,
11 | "skipLibCheck": true,
12 | "esModuleInterop": true,
13 | "sourceMap": true,
14 | "declaration": false,
15 | "experimentalDecorators": true,
16 | "moduleResolution": "bundler",
17 | "importHelpers": true,
18 | "target": "ES2022",
19 | "module": "ES2022",
20 | "useDefineForClassFields": false,
21 | "lib": [
22 | "ES2022",
23 | "dom"
24 | ]
25 | },
26 | "angularCompilerOptions": {
27 | "enableI18nLegacyMessageIdFormat": false,
28 | "strictInjectionParameters": true,
29 | "strictInputAccessModifiers": true,
30 | "strictTemplates": true
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/spec",
6 | "types": [
7 | "jasmine"
8 | ]
9 | },
10 | "include": [
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------