Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
339 changes: 339 additions & 0 deletions packages/preview/smartart/0.1.0/LICENSE

Large diffs are not rendered by default.

249 changes: 249 additions & 0 deletions packages/preview/smartart/0.1.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
# smartart

SmartArt-style diagrams for Typst: card-table, process, gantt, pyramid, hierarchy, steps, venn, timeline, cycle, tree, matrix, and more.

## Installation

```typst
#import "@preview/smartart:0.1.0": *
```

## Widgets

### card-table
A card-style table with rounded cells, coloured header, and alternating row fills.

```typst
#card-table(
("Study", "Approach", "Dataset"),
(
("Guo et al.", "Propose two...", "Homemade"),
("Gurunathan", "Exhaustive...", "PUT Vein"),
("Zhang et al.", "ML-based", "InHouse"),
),
)
```

![Screenshot of the card-table widget showing a styled data table with headers and rows](images/card-table.png)

### gantt
A Gantt chart with task bars, progress indicator, grid lines, and a "today" marker.

```typst
#gantt(
(
("Planning", 0, 12, 100),
("Development", 6, 30, 60),
("Testing", 24, 40, 30),
("Papers", 0, 48, 20, false),
),
span: 48, grid-step: 12,
periods: ("Year 1", "Year 2", "Year 3", "Year 4"),
today: 20,
)
```

![Screenshot of the gantt chart widget with task bars, progress indicators, and a today marker](images/gantt.png)

### process
A heartbeat-ring process diagram with icon badges and connector arms. Requires [Font Awesome 7 Free](https://fontawesome.com).

```typst
#process(
(
("\u{f02d}", "1. Review methods"),
("\u{f51e}", "2. Data collection"),
("\u{f83e}", "3. Signal analysis"),
),
)
```

![Screenshot of the process diagram widget showing a heartbeat ring with connected icon badges](images/process.png)

### pyramid
A pyramid or funnel diagram (use `flip: true` for a funnel).

```typst
#pyramid(([Vision], [Strategy], [Tactics]))
```

![Screenshot of the pyramid widget showing stacked triangular levels](images/pyramid.png)

### hierarchy
A root node with a row of children beneath it.

```typst
#hierarchy([CEO], (([Eng], rgb("#a7dd9b")), [Sales], [HR]))
```

![Screenshot of the hierarchy widget showing a root node with child nodes beneath](images/hierarchy.png)

### steps
A vertical numbered list of steps.

```typst
#steps(([Plan], [Execute], [Review], ([Deploy], rgb("#e64553"))))
```

![Screenshot of the steps widget showing vertical numbered step blocks](images/steps.png)

### venn
A 2- or 3-circle Venn diagram.

```typst
#venn((([Behavior], rgb("#aab4f7")), [Signal], [Security]))
```

![Screenshot of the venn diagram widget showing three overlapping circles](images/venn.png)

### hlist
A horizontal row of equally sized coloured blocks.

```typst
#hlist(([Plan], [Execute], ([Review], rgb("#e64553"))))
```

![Screenshot of the hlist widget showing equally sized coloured blocks in a row](images/hlist.png)

### chevron
A sequence of right-pointing chevron arrows.

```typst
#chevron(([Phase 1], [Phase 2], [Phase 3], [Phase 4]))
```

![Screenshot of the chevron widget showing sequential right-pointing arrow blocks](images/chevron.png)

### cycle
Nodes arranged on a ring connected by curved arrows.

```typst
#cycle(([Plan], [Do], [Check], ([Act], rgb("#e64553"))))
```

![Screenshot of the cycle widget showing nodes arranged on a ring with curved arrows](images/cycle.png)

### target
Concentric rings (bullseye).

```typst
#target(([Vision], [Mission], [Goal]))
```

![Screenshot of the target widget showing concentric rings in a bullseye pattern](images/target.png)

### matrix
A 2x2 matrix with optional axis labels.

```typst
#matrix(([TL], [TR], [BL], [BR]),
x-axis: ("Low", "High"),
y-axis: ("High", "Low"))
```

![Screenshot of the matrix widget showing a 2x2 grid with axis labels](images/matrix.png)

### snake
A bending process that wraps into multiple rows.

```typst
#snake(([Step 1], [Step 2], [Step 3], [Step 4], [Step 5], [Step 6]))
```

![Screenshot of the snake widget showing a bending process that wraps into rows](images/snake.png)

### stairs
An ascending stair-step process.

```typst
#stairs(([Plan], [Develop], ([Launch], rgb("#e64553"))))
```

![Screenshot of the stairs widget showing an ascending stair-step process](images/stairs.png)

### gears
Up to 3 interlocking cogwheels.

```typst
#gears(([Research], [Development], [Production]))
```

![Screenshot of the gears widget showing interlocking cogwheels](images/gears.png)

### timeline
A horizontal timeline with alternating labels.

```typst
#timeline((("2024", [Start]), ("2025", [Pilot]), ("2026", [Launch])))
```

![Screenshot of the timeline widget showing milestones along a horizontal line](images/timeline.png)

### tree
A multi-level tree hierarchy.

```typst
#tree(([CEO], (([Eng], ([Web], [Mobile])), [Sales])))
```

![Screenshot of the tree widget showing a multi-level hierarchy chart](images/tree.png)

### arrows
Converging or diverging arrows around a central core.

```typst
// converging
#arrows(([Idea 1], [Idea 2], [Idea 3]), core: [Core])

// diverging
#arrows(([Branch 1], [Branch 2]), diverge: true)
```

![Screenshot of converging arrows widget showing arrows pointing inward to a central core](images/arrows-converging.png)
![Screenshot of diverging arrows widget showing arrows pointing outward from a central core](images/arrows-diverging.png)

### opposing
Two block arrows facing each other.

```typst
#opposing(([Pros], [Cons]))
```

![Screenshot of the opposing widget showing two block arrows facing each other](images/opposing.png)

### equation
An A + B = C equation-style diagram.

```typst
#equation(([Input 1], [Input 2], [Output]))
```

![Screenshot of the equation widget showing an A plus B equals C diagram](images/equation.png)

### kpi
Stat cards displaying a large value and a caption.

```typst
#kpi((("< 1%", [Target EER]),
("99%", [Accuracy], rgb("#40a02b")),
("500+", [Users])))
```

![Screenshot of the kpi widget showing stat cards with big values and captions](images/kpi.png)

### pill-steps
A central hub with connected pill-shaped step rows. Requires [Font Awesome 7 Free](https://fontawesome.com) for icons.

```typst
#pill-steps(
(
([Research], [Gather requirements],
text(font: "Font Awesome 7 Free", size: 26pt)[\u{f0eb}]),
([Develop], [Build the solution],
text(font: "Font Awesome 7 Free", size: 26pt)[\u{f0ae}], rgb("#74c7ec")),
),
title: [PROJECT STEPS],
)
```

![Screenshot of the pill-steps widget showing a central hub with connected pill-shaped step rows](images/pill-steps.png)
41 changes: 41 additions & 0 deletions packages/preview/smartart/0.1.0/arrows.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Converging or diverging arrows to/from a centre. Import with: #import "arrows.typ": arrows
//
// #arrows(([Idea 1], [Idea 2], [Idea 3]), core: [Core])
// #arrows(([Branch 1], [Branch 2]), diverge: true)
#import "@preview/cetz:0.5.2": canvas, draw
#import "common.typ": palette, _lab, _col

#let arrows(
items,
core: none,
diverge: false,
radius: 4.8,
bw: 3.6, bh: 1.6,
text-fill: white, size: 16pt,
core-fill: rgb("#1f1f3a"), core-r: 1.4,
) = canvas({
import draw: *
let n = items.len()
let ang = i => 90deg - i * 360deg / n
for (i, it) in items.enumerate() {
let a = ang(i)
let col = _col(it, i)
let nearbox = ((radius - 1.1) * calc.cos(a), (radius - 1.1) * calc.sin(a))
let nearctr = ((core-r + 0.4) * calc.cos(a), (core-r + 0.4) * calc.sin(a))
if diverge {
line(nearctr, nearbox, mark: (end: ">", fill: col), stroke: col + 6pt)
} else {
line(nearbox, nearctr, mark: (end: ">", fill: col), stroke: col + 6pt)
}
let bx = (radius * calc.cos(a), radius * calc.sin(a))
rect((bx.at(0) - bw / 2, bx.at(1) - bh / 2), (bx.at(0) + bw / 2, bx.at(1) + bh / 2),
fill: col, stroke: none, radius: 0.15)
content(bx, box(width: (bw - 0.4) * 1cm,
align(center, text(fill: text-fill, weight: "bold", size: size)[#_lab(it)])))
}
circle((0, 0), radius: core-r, fill: core-fill, stroke: white + 2pt)
if core != none {
content((0, 0), box(width: (2 * core-r - 0.3) * 1cm,
align(center, text(fill: white, weight: "bold", size: size)[#core])))
}
})
27 changes: 27 additions & 0 deletions packages/preview/smartart/0.1.0/chevron.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Chevron: sequential right-pointing arrows. Import with: #import "chevron.typ": chevron
//
// #chevron(([Phase 1], [Phase 2], ([Phase 3], rgb("#e64553"))))
#import "@preview/cetz:0.5.2": canvas, draw
#import "common.typ": palette, _lab, _col

#let chevron(
items,
w: 5,
h: 2.4,
notch: 0.9,
text-fill: white,
size: 18pt,
) = canvas({
import draw: *
let n = items.len()
let step = w - notch
let x0 = -(n * step) / 2
for (i, it) in items.enumerate() {
let x = x0 + i * step
line((x, -h / 2), (x + w - notch, -h / 2), (x + w, 0),
(x + w - notch, h / 2), (x, h / 2), (x + notch, 0),
close: true, fill: _col(it, i), stroke: white + 1.5pt)
content((x + w / 2 + notch / 2, 0), box(width: (w - notch) * 1cm,
align(center, text(fill: text-fill, weight: "bold", size: size)[#_lab(it)])))
}
})
11 changes: 11 additions & 0 deletions packages/preview/smartart/0.1.0/common.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Shared utilities: colour palette and item-accessor helpers.
// Import with: #import "common.typ": palette, _lab, _col
#let palette = (
rgb("#aab4f7"), // lavender
rgb("#a7dd9b"), // green
rgb("#f9c74f"), // amber
rgb("#e64553"), // red
rgb("#74c7ec"), // sky
)
#let _lab(it) = if type(it) == array { it.at(0) } else { it }
#let _col(it, i) = if type(it) == array and it.len() > 1 { it.at(1) } else { palette.at(calc.rem(i, palette.len())) }
33 changes: 33 additions & 0 deletions packages/preview/smartart/0.1.0/cycle.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Cycle: nodes on a ring joined by curved arrows. Import with: #import "cycle.typ": cycle
//
// #cycle(([Plan], [Do], [Check], ([Act], rgb("#e64553"))))
#import "@preview/cetz:0.5.2": canvas, draw
#import "common.typ": palette, _lab, _col

#let cycle(
items,
radius: auto,
node: 1.5,
arrow: rgb("#73c25a"),
text-fill: white,
size: 16pt,
) = canvas({
import draw: *
let n = items.len()
let R = if radius == auto { calc.max(3, n * 0.9) } else { radius }
let ang = i => 90deg - i * 360deg / n
let gapd = calc.asin(calc.min(0.99, node / R)) + 7deg
for i in range(n) {
let a0 = ang(i) - gapd
let a1 = ang(calc.rem(i + 1, n)) + gapd
if a1 > a0 { a1 = a1 - 360deg }
arc((R * calc.cos(a0), R * calc.sin(a0)), start: a0, stop: a1, radius: R,
mark: (end: ">", fill: arrow), stroke: arrow + 3pt)
}
for (i, it) in items.enumerate() {
let p = (R * calc.cos(ang(i)), R * calc.sin(ang(i)))
circle(p, radius: node, fill: _col(it, i), stroke: white + 2pt)
content(p, box(width: (2 * node - 0.5) * 1cm,
align(center, text(fill: text-fill, weight: "bold", size: size)[#_lab(it)])))
}
})
27 changes: 27 additions & 0 deletions packages/preview/smartart/0.1.0/equation.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Equation: A + B = C (last item is result). Import with: #import "equation.typ": equation
//
// #equation(([Input 1], [Input 2], [Output]))
#import "@preview/cetz:0.5.2": canvas, draw
#import "common.typ": palette, _lab, _col

#let equation(
items,
w: 3.6, h: 2.4, gap: 1.6,
text-fill: white, size: 18pt, op-size: 32pt,
op-fill: rgb("#1f1f3a"), radius: 0.15,
) = canvas({
import draw: *
let n = items.len()
let pitch = w + gap
let x0 = -((n - 1) * pitch) / 2
for (i, it) in items.enumerate() {
let cx = x0 + i * pitch
if i > 0 {
content((cx - pitch / 2, 0),
text(fill: op-fill, weight: "bold", size: op-size)[#(if i == n - 1 { "=" } else { "+" })])
}
rect((cx - w / 2, -h / 2), (cx + w / 2, h / 2), fill: _col(it, i), stroke: none, radius: radius)
content((cx, 0), box(width: (w - 0.4) * 1cm,
align(center, text(fill: text-fill, weight: "bold", size: size)[#_lab(it)])))
}
})
Loading
Loading