Skip to content

Commit 0b4c331

Browse files
committed
Merge branch 'main' of https://github.com/NotePlan/plugins
2 parents 2b19684 + 8bcefbf commit 0b4c331

16 files changed

Lines changed: 2225 additions & 67 deletions
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(node:*)"
5+
],
6+
"deny": [],
7+
"ask": []
8+
}
9+
}

grdn.TagTracker/plugin.json

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
{
2+
"macOS.minVersion": "10.13.0",
3+
"noteplan.minAppVersion": "3.20",
4+
"plugin.releaseStatus": "beta",
5+
"plugin.id": "grdn.TagTracker",
6+
"plugin.name": "📊 Tag Tracker",
7+
"plugin.description": "Track and visualize tag values over time with interactive charts. Monitor @sleep, @sleep_deep, @rps, @alcohol, and @bedtime across your daily notes. Toggle between line and bar chart views.",
8+
"plugin.author": "grdn",
9+
"plugin.version": "1.1.0",
10+
"plugin.dependencies": [],
11+
"plugin.requiredFiles": [],
12+
"plugin.script": "script.js",
13+
"plugin.commands": [
14+
{
15+
"name": "showTagTracker",
16+
"description": "Show tag frequency tracker with line graph visualization",
17+
"jsFunction": "showTagTracker"
18+
}
19+
],
20+
"plugin.settings": [
21+
{
22+
"type": "heading",
23+
"title": "Chart Color Settings"
24+
},
25+
{
26+
"key": "customColor1",
27+
"title": "Color 1 (Hex Code)",
28+
"description": "First chart color (default: #0a84ff - blue)",
29+
"type": "string",
30+
"default": "#0a84ff",
31+
"required": false
32+
},
33+
{
34+
"key": "customColor2",
35+
"title": "Color 2 (Hex Code)",
36+
"description": "Second chart color (default: #bf5af2 - purple)",
37+
"type": "string",
38+
"default": "#bf5af2",
39+
"required": false
40+
},
41+
{
42+
"key": "customColor3",
43+
"title": "Color 3 (Hex Code)",
44+
"description": "Third chart color (default: #32d74b - green)",
45+
"type": "string",
46+
"default": "#32d74b",
47+
"required": false
48+
},
49+
{
50+
"key": "customColor4",
51+
"title": "Color 4 (Hex Code)",
52+
"description": "Fourth chart color (default: #ff453a - red)",
53+
"type": "string",
54+
"default": "#ff453a",
55+
"required": false
56+
},
57+
{
58+
"key": "customColor5",
59+
"title": "Color 5 (Hex Code)",
60+
"description": "Fifth chart color (default: #ffd60a - yellow)",
61+
"type": "string",
62+
"default": "#ffd60a",
63+
"required": false
64+
},
65+
{
66+
"key": "customColor6",
67+
"title": "Color 6 (Hex Code)",
68+
"description": "Sixth chart color (default: #ff9f0a - orange)",
69+
"type": "string",
70+
"default": "#ff9f0a",
71+
"required": false
72+
},
73+
{
74+
"key": "customColor7",
75+
"title": "Color 7 (Hex Code)",
76+
"description": "Seventh chart color (default: #64d2ff - cyan)",
77+
"type": "string",
78+
"default": "#64d2ff",
79+
"required": false
80+
},
81+
{
82+
"key": "customColor8",
83+
"title": "Color 8 (Hex Code)",
84+
"description": "Eighth chart color (default: #ff375f - pink)",
85+
"type": "string",
86+
"default": "#ff375f",
87+
"required": false
88+
},
89+
{
90+
"key": "customColor9",
91+
"title": "Color 9 (Hex Code)",
92+
"description": "Ninth chart color (default: #30d158 - mint)",
93+
"type": "string",
94+
"default": "#30d158",
95+
"required": false
96+
},
97+
{
98+
"key": "customColor10",
99+
"title": "Color 10",
100+
"description": "Tenth chart color (default: #ac8e68 - brown)",
101+
"type": "string",
102+
"default": "#ac8e68",
103+
"required": false
104+
},
105+
{
106+
"key": "customColor11",
107+
"title": "Color 11",
108+
"description": "Eleventh chart color (default: #5856d6 - indigo)",
109+
"type": "string",
110+
"default": "#5856d6",
111+
"required": false
112+
},
113+
{
114+
"key": "customColor12",
115+
"title": "Color 12",
116+
"description": "Twelfth chart color (default: #ff2d55 - rose)",
117+
"type": "string",
118+
"default": "#ff2d55",
119+
"required": false
120+
},
121+
{
122+
"type": "separator"
123+
},
124+
{
125+
"type": "heading",
126+
"title": "Color Format Instructions\nSupported: Hex (#F00, #FF0000), Named (red, blue), RGB (rgb(255,0,0)), HSL (hsl(0,100%,50%)).\nColors cycle if you have 12+ habits."
127+
}
128+
]
129+
}

helpers/colors.js

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Helper functions for working with colors
22
// Uses chroma.js, a fantastic utility for deriving colors https://gka.github.io/chroma.js/
3+
// NOTE: DO NOT FLOW TYPE THIS FILE. IT IS IMPORTED BY SOME JSX FILES AND FOR SOME REASON, ROLLUP CHOKES ON FLOW.
34

45
import chroma from 'chroma-js'
56
import { logDebug, logError, logInfo, logWarn } from '@helpers/dev'
@@ -15,7 +16,6 @@ export const isLight = (bgColor) => !isDark(bgColor)
1516
* @returns {string} - the calculated altColor in #hex format
1617
*/
1718
// export const getAltColor = (bgColor: string, strength: number = 0.2): string => {
18-
// NOTE: DO NOT FLOW TYPE THIS FUNCTION. IT IS IMPORTED BY JSX FILE AND FOR SOME REASON, ROLLUP CHOKES ON FLOW
1919
export const getAltColor = (bgColor, strength = 0.2) => {
2020
const calcAltFromBGColor = isLight(bgColor) ? chroma(bgColor).darken(strength).css() : chroma(bgColor).brighten(strength).css()
2121
// if (!altColor || chroma.deltaE(bgColor,altColor) < ) return calcAltFromBGColor
@@ -337,12 +337,44 @@ export const getColorStyle = (color) => {
337337
return `var(--${color}, inherit)`
338338
}
339339

340+
/**
341+
* Convert Tailwind color definitions to RGBA format suitable for CSS style statements
342+
* @param {string} color - Tailwind color name (e.g., "amber-200", "slate-800") or hex/rgb/rgba string
343+
* @param {number} opacity - Opacity value between 0 and 1 (default: 1)
344+
* @returns {string} - RGBA color string in modernised format "rgba(r g b / a)"
345+
* @example
346+
* tailwindToRgba('amber-200') // returns "rgba(255, 245, 235, 1)"
347+
* tailwindToRgba('slate-800') // returns "rgba(30, 32, 34, 1)"
348+
* tailwindToRgba('blue-500') // returns "rgba(59, 130, 246, 1)"
349+
* tailwindToRgba('#3b82f6', 0.5) // returns "rgba(59, 130, 246, 0.5)"
350+
*/
351+
export function tailwindToRgbWithOpacity(color, opacity = 1) {
352+
let hex = ''
353+
// Check if it's a Tailwind color name (e.g., "amber-200")
354+
if (/^[a-z]+-\d+$/i.test(color)) {
355+
hex = TAILWIND_COLORS[color]
356+
} else {
357+
logWarn(`tailwindToRgba`, `Invalid Tailwind color name: ${color}`)
358+
return null
359+
}
360+
361+
// Parse RGB values
362+
const r = parseInt(hex.substring(0, 2), 16)
363+
const g = parseInt(hex.substring(2, 4), 16)
364+
const b = parseInt(hex.substring(4, 6), 16)
365+
// If alpha channel is present (#RRGGBBAA), then return as is
366+
if (opacity !== 1) {
367+
return `rgb(${r} ${g} ${b} / ${opacity})`
368+
}
369+
return hex
370+
}
371+
340372
/**
341373
* Convert Tailwind color definitions to HSL format suitable for CSS style statements
342374
* Accepts Tailwind color names (e.g., "amber-200", "slate-800") or any chroma-parseable color format
343375
* @param {string} color - Tailwind color name (e.g., "amber-200", "slate-800") or hex/rgb/rgba string
344376
* @param {boolean} includeAlpha - Whether to include alpha channel in output (default: false)
345-
* @returns {string} - HSL color string in format "hsl(h, s%, l%)" or "hsla(h, s%, l%, a)"
377+
* @returns {string} - HSL color string in modernised format "hsl(h s l)" or "hsla(h s l / a)"
346378
* @example
347379
* tailwindToHsl('amber-200') // returns "hsl(45, 93%, 77%)"
348380
* tailwindToHsl('slate-800') // returns "hsl(222, 47%, 11%)"
@@ -384,13 +416,79 @@ export const tailwindToHsl = (color, includeAlpha = false) => {
384416

385417
if (includeAlpha) {
386418
const alpha = chromaColor.alpha()
387-
return `hsla(${h}, ${s}%, ${l}%, ${alpha})`
419+
return `hsla(${h} ${s}% ${l}% / ${alpha})`
388420
}
389421

390-
return `hsl(${h}, ${s}%, ${l}%)`
422+
return `hsl(${h} ${s}% ${l}%)`
391423
} catch (error) {
392424
// If chroma can't parse the color, return null
393425
logError(`tailwindToHsl`, `Error: ${error.message}`)
394426
return null
395427
}
396428
}
429+
430+
/**
431+
* Convert any CSS color to rgba with specified opacity
432+
* Supports: #RGB, #RRGGBB, #RRGGBBAA, named CSS colors (e.g. red, blue), tailwind colors (amber-200, blue-500, etc.), hsl(), rgb(), rgba()
433+
* @param {string} color - CSS color value
434+
* @param {number} opacity - Opacity value between 0 and 1 (default: 1)
435+
* @returns {string} RGBA color string
436+
*/
437+
export function colorToModernSpecWithOpacity(colorIn, opacity = 1) {
438+
let color = colorIn.trim().toLowerCase()
439+
440+
// First convert Tailwind color names to rgb()
441+
if (/^\w+-\d+$/.test(color)) {
442+
color = tailwindToRgbWithOpacity(color)
443+
}
444+
445+
// If already rgb(), add opacity if needed
446+
if (color.startsWith('rgb(') && opacity !== 1) {
447+
// Convert rgb(r,g,b) or rgb(r g b) to rgb(r g b / opacity)
448+
return color
449+
.replace(',', ' ', 'g')
450+
.replace(')', `, ${opacity})`)
451+
}
452+
453+
// If already hsl(), overwrite opacity if needed
454+
if (color.startsWith('hsl(') && opacity !== 1) {
455+
// Convert hsl(h,s,l) or hsl(h s l) to hsl(h s l / opacity)
456+
return color
457+
.replace(',', ' ', 'g')
458+
.replace(')', ` / ${opacity})`)
459+
}
460+
461+
// If already rgba() return as-is
462+
if (color.startsWith('rgba(')) {
463+
return color
464+
}
465+
466+
// Handle hex colors (#RGB, #RRGGBB, #RRGGBBAA)
467+
if (color.startsWith('#')) {
468+
let hex = color.substring(1)
469+
470+
// Expand shorthand #RGB to #RRGGBB
471+
if (hex.length === 3) {
472+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]
473+
}
474+
475+
// Parse RGB values
476+
const r = parseInt(hex.substring(0, 2), 16)
477+
const g = parseInt(hex.substring(2, 4), 16)
478+
const b = parseInt(hex.substring(4, 6), 16)
479+
480+
// Check if alpha channel is present (#RRGGBBAA)
481+
if (hex.length === 8) {
482+
const a = parseInt(hex.substring(6, 8), 16) / 255
483+
return `rgba(${r} ${g} ${b} / ${a})`
484+
}
485+
486+
return `rgba(${r} ${g} ${b} / ${opacity})`
487+
}
488+
489+
// For named colors (red, blue, etc.), add opacity (if wanted) using color-mix()
490+
if (opacity !== 1) {
491+
return `color-mix(in srgb, ${color} ${opacity * 100}%, transparent)`
492+
}
493+
return color
494+
}

jgclark.Summaries/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
# What's Changed in ⏱ Habits and Summaries plugin?
22
(And see the full [README](https://github.com/NotePlan/plugins/tree/main/jgclark.Summaries).)
33

4+
## [1.1.0.b1] - 2026-02-02 (private beta)
5+
- Added **/Chart Summary Stats** command. This ???. (It was prototyped by @grdn and then integrated, updated and made maintainable by @jgclark.)
6+
### Significant changes since prototype
7+
- Added to NP sidebar
8+
- Moved all configuration from code to settings system
9+
- Simplified specifying colors for charts, and added Tailwind color support.
10+
- Chart stats now track which tags include any time-based values and display their sums and averages in HH:MM format (not decimal) in the summary and tooltips. This can be overriden by the "Tags to display using time format" setting.
11+
- yes/no habits can be specified in a calendar note as either:
12+
- the habit as a completed task or checklist item;
13+
- For hashtag or @mention: counts how many times the tag appears in any line.
414

515
## [1.0.3] - 2026-01-30 (unreleased)
616
- worked around a new bug in the API for getting hashtags and mentions that meant some were being ignored, affecting the accuracy of the plugin's output.

0 commit comments

Comments
 (0)